<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">






	<title>NHibernate Best Practices with ASP.NET, 1.2nd Ed. - CodeProject</title> 
	




	

<meta name="Description" content="This article describes best practices for leveraging the benefits of NHibernate 1.2, ASP.NET, generics and unit testing together.; Author: Billy McCafferty; Section: Design and Architecture; Chapter: Development Lifecycle">
<meta name="Keywords" content="SQL2000, C#, ASP.NET, Windows, .NET, Visual-Studio, DBA, Dev, WebForms, Advanced,Design and Architecture,Development Lifecycle,Free source code, tutorials">
<meta name="Author" content="The Code Project">
<meta name="Rating" content="General">
<meta name="Robots" content="index, follow">
<meta name="Revisit-After" content="1 days">
<link rel="alternate" type="application/rss+xml" title="CodeProject Latest articles - All topics" href="http://www.codeproject.com/webservices/articlerss.aspx?cat=1">
<link rel="alternate" type="application/rss+xml" title="CodeProject Latest articles - MFC / C++" href="http://www.codeproject.com/webservices/articlerss.aspx?cat=2">
<link rel="alternate" type="application/rss+xml" title="CodeProject Latest articles - C#" href="http://www.codeproject.com/webservices/articlerss.aspx?cat=3">
<link rel="alternate" type="application/rss+xml" title="CodeProject Latest articles - ASP.NET" href="http://www.codeproject.com/webservices/articlerss.aspx?cat=4">
<link rel="alternate" type="application/rss+xml" title="CodeProject Latest articles - .NET" href="http://www.codeproject.com/webservices/articlerss.aspx?cat=5">
<link rel="alternate" type="application/rss+xml" title="CodeProject Latest articles - VB.NET" href="http://www.codeproject.com/webservices/articlerss.aspx?cat=6">
<link rel="alternate" type="application/rss+xml" title="CodeProject Lounge Postings" href="http://www.codeproject.com/webservices/LoungeRSS.aspx">
<link rel="search" type="application/opensearchdescription+xml" title="CodeProject" href="http://www.codeproject.com/info/OpenSearch.xml">
	<base target="_top">
	<link rel="icon" href="favicon.ico" type="image/ico">
<link rel="shortcut icon" href="favicon.ico" type="image/ico">




	



<link rel="stylesheet" type="text/css" href="index.css" media="all">
</head>
<body>

<a href="#Main"><img alt="Click here to Skip to main content" src="t.gif" style="border-style: none; position: absolute; top: 0pt; left: 0pt; width: 1px; height: 1px; z-index: 100;"></a>

<div style="margin: 0px; padding: 0px; width: 100%;">
	<div style="width: 100%;">

<table class="MemberNavBar" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr>
<td style="font-weight: bold;">6,756,135 members and growing! (12,942 online)</td>
<td align="right">



<div id="ctl00_MemberMenu_LoggedOffOptions" class="MemberNavBarText" style="margin: 0pt; padding: 0pt;">
	<a name="SignUp"></a>
<form name="subForm" id="subForm" action="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx" method="post" style="margin: 0pt; padding: 0pt;">

<!-- This hidden field is used for identifying form which has made post request.
     (This form posts to another page and we need to know which form did the post request) -->
<input id="FormName" name="FormName" value="MenuBarForm" type="hidden">

Email    <input value="" class="SmallText" name="Email" id="Email" style="width: 100px;" type="text">
Password <input class="SmallText" name="Password" id="Password" style="width: 60px;" type="password">
<input value="Sign in" class="FormButton" type="submit">
<input class="FormButton" onclick="return Join();" value="Join" type="button"><input name="fld_quicksign" value="true" type="hidden">
<input checked="checked" name="RememberMeCheck" id="RememberMeCheck" value="1" type="checkbox">
<label for="RememberMeCheck">Remember me?</label>&nbsp;
<a id="ctl00_MemberMenu_SendPassword" href="http://www.codeproject.com/script/Membership/SendPassword.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx"><img alt="help" src="help.gif" align="middle" border="0" height="16px" width="16px">Lost your password?</a>
</form>

</div>

</td>
</tr>
</tbody></table></div>
	<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr>
		<td class="HeaderLogo"><a href="http://www.codeproject.com/"><img id="ctl00_Logo" src="logo225x90.gif" alt="The Code Project" style="border-width: 0px; height: 90px; width: 225px;"></a></td>				 
		<td class="HeaderBanner" align="right" width="100%"><iframe src="index_1.html" scrolling="no" frameborder="0" height="90px" width="728px"></iframe></td>
	</tr></tbody></table>
	

<div class="NavBarMain">
<ul id="nav">

<li><a href="http://www.codeproject.com/">Home</a></li>
<li><a id="ctl00_TopNavBar_Art" class="down" href="http://www.codeproject.com/script/Articles/Latest.aspx">Articles</a>



	<ul class="flyout">
		<li><a id="ctl00_TopNavBar_ArtSearch" class="fly break" href="http://www.codeproject.com/info/search.aspx">Search</a></li>
		<li><a id="ctl00_TopNavBar_ArtLatestArts" class="fly" href="http://www.codeproject.com/script/Articles/Latest.aspx">Latest Articles</a></li>
		<li><a id="ctl00_TopNavBar_ArtLatestTips" class="fly" href="http://www.codeproject.com/script/Articles/Latest.aspx?at=6">Latest Tips/Tricks</a></li>
		<li><a id="ctl00_TopNavBar_ArtTop" class="fly" href="http://www.codeproject.com/script/Articles/TopArticles.aspx?ta_so=4">Top Articles</a></li>
		<li><a id="ctl00_TopNavBar_ArtBeginner" class="fly" href="http://www.codeproject.com/info/search.aspx?vidlst=152&amp;sa_us=True">Beginner Articles</a></li>
		<li><a id="ctl00_TopNavBar_ArtBlogArticles" class="fly break" href="http://www.codeproject.com/script/Articles/BlogArticleList.aspx">Technical Blogs</a></li>
		<li><a id="ctl00_TopNavBar_ArtPostArticle" class="fly" href="http://www.codeproject.com/info/Submit.aspx">Post an Article</a></li>
		<li><a id="ctl00_TopNavBar_ArtPostTipTrick" class="fly" href="http://www.codeproject.com/script/Answers/Post.aspx?new=tipntrick">Post Tip/Trick</a></li>
		<li><a id="ctl00_TopNavBar_ArtPostBlog" class="fly break" href="http://www.codeproject.com/script/Articles/BlogFeed.aspx">Post your Blog</a></li>
		<li><a id="ctl00_TopNavBar_ArtGuide" class="fly" href="http://www.codeproject.com/info/Submit.aspx">Posting/Update Guidelines</a></li>
		<li><a id="ctl00_TopNavBar_ArtCompetition" class="fly" href="http://www.codeproject.com/script/Awards/CurrentCompetitions.aspx?cmpTpId=1">Article Competition</a></li>
		<li><a id="ctl00_TopNavBar_ArtTopicList" class="last" href="http://www.codeproject.com/script/Content/SiteMap.aspx">Topic List</a></li>
	</ul>

</li>



<li><a id="ctl00_TopNavBar_Answers" href="http://www.codeproject.com/script/Answers/List.aspx?tab=unanswered">Quick Answers</a>
	<ul class="flyout">
		<li><a id="ctl00_TopNavBar_QAAsk" class="fly" href="http://www.codeproject.com/script/Answers/Post.aspx?new=question">Ask a Question</a></li>
		<li><a id="ctl00_TopNavBar_QAUnanswered" class="fly" href="http://www.codeproject.com/script/Answers/List.aspx?tab=unanswered">List unanswered Questions</a></li>
		
	</ul>

</li>



<li><a id="ctl00_TopNavBar_MessageBoards" class="down" href="http://www.codeproject.com/script/Forums/List.aspx">Message Boards</a>

	<ul class="flyout">
		<li><a class="fly" href="http://www.codeproject.com/Forums/12076/ASP-NET.aspx">ASP.NET</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/4486/ATL-WTL-STL.aspx">ATL /  WTL / STL</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1647/C-Cplusplus-MFC.aspx">C / C++ / MFC</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/3785/Managed-Cplusplus-CLI.aspx">Managed C++/CLI</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1649/Csharp.aspx">C#</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1648/COM.aspx">COM</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/186301/Hardware-Devices.aspx">Hardware &amp; Devices</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1004117/LINQ.aspx">LINQ</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1650/NET-Framework.aspx">.NET Framework</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1644/System-Admin.aspx">System Admin</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1004257/Silverlight.aspx">Silverlight</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1725/General-Database.aspx">General Database</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1540733/Sharepoint.aspx">Sharepoint</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1646/Visual-Basic.aspx">Visual Basic</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1640/Web-Development.aspx">Web Development</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1004114/WPF-WCF-WF.aspx">WPF / WCF / WF</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/3421/XML-XSL.aspx">XML / XSL</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1642/General-IT-Issues.aspx">General IT Issues</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1645/Site-Bugs-Suggestions.aspx">Site Bugs / Suggestions</a></li>
<li><a class="fly" href="http://www.codeproject.com/Forums/1536756/The-Soapbox-2-0.aspx">The Soapbox 2.0</a></li>

		<li><a id="ctl00_TopNavBar_MessageBoardsAll" class="last" href="http://www.codeproject.com/script/Forums/List.aspx">All Message Boards...</a></li>
	</ul>

</li>



<li><a id="ctl00_TopNavBar_Job" href="http://www.codeproject.com/script/Jobs/List.aspx">Job Board</a>
	<ul class="flyout">
		<li><a id="ctl00_TopNavBar_JobLatest" class="fly" href="http://www.codeproject.com/script/Jobs/List.aspx">Latest</a></li>
		<li><a id="ctl00_TopNavBar_JobSearch" class="fly" href="http://www.codeproject.com/script/Jobs/Search.aspx">Search</a></li>
		<li><a id="ctl00_TopNavBar_JobPost" class="fly" href="http://www.codeproject.com/script/Jobs/Edit.aspx">Post a Job</a></li>
		<li><a id="ctl00_TopNavBar_JobFaq" class="last" href="http://www.codeproject.com/script/Jobs/FAQ.aspx">FAQ and Pricing</a></li>
	</ul>

</li>




<li><a id="ctl00_TopNavBar_Cat" href="http://www.codeproject.com/script/Catalog/List.aspx">Catalog</a>
	<ul class="flyout">
		<li><a id="ctl00_TopNavBar_CatLatest" class="fly" href="http://www.codeproject.com/script/Catalog/List.aspx?ctls=DatePostedDescending">Latest</a></li>
		<li><a id="ctl00_TopNavBar_CatSearch" class="fly" href="http://www.codeproject.com/script/Catalog/List.aspx">Search</a></li>
		<li><a id="ctl00_TopNavBar_CatPost" class="fly" href="http://www.codeproject.com/script/Catalog/Edit.aspx">Post a Catalog Item</a></li>
		<li><a id="ctl00_TopNavBar_CatFaq" class="last" href="http://www.codeproject.com/script/Catalog/FAQ.aspx">FAQ and Pricing</a></li>
	</ul>

</li>






<li><a id="ctl00_TopNavBar_Help" href="http://www.codeproject.com/info/FAQ.aspx">Help!</a>

	<ul class="flyout">
		<li><a id="ctl00_TopNavBar_HelpWhatIs" class="fly" href="http://www.codeproject.com/info/guide.aspx">What is 'The Code Project'?</a></li>
		<li><a id="ctl00_TopNavBar_HelpGeneral" class="fly" href="http://www.codeproject.com/info/FAQ.aspx">General FAQ</a></li>
		<li><a id="ctl00_TopNavBar_HelpPostQuestion" class="fly" href="http://www.codeproject.com/script/Forums/List.aspx">Post a Question</a></li>
		<li><a id="ctl00_TopNavBar_HelpSiteMap" class="fly" href="http://www.codeproject.com/script/Content/SiteMap.aspx">Site Directory</a></li>
		<li><a id="ctl00_TopNavBar_HelpAboutUs" class="last" href="http://www.codeproject.com/info/about.aspx">About Us</a></li>
	</ul>

</li>


<li style="float: right;">
<a id="ctl00_TopNavBar_Lounge" href="http://www.codeproject.com/Lounge.aspx">Lounge</a>
<a id="ctl00_TopNavBar_Soapbox" href="javascript:void();" style="display: none;">Soapbox</a>

</li>

</ul>

</div>
	<div style="width: 100%;"><a name="_top"></a><table id="ctl00_ArticleTopHeader_HeaderTable" class="ArticleHeader" cellpadding="3" width="100%">
	<tbody><tr valign="top">
		<td class="SmallText">
	
	<a id="ctl00_ArticleTopHeader_ChapterLink" href="http://www.codeproject.com/script/Content/Chapter.aspx?chptId=11">Development Lifecycle</a> »
	<a id="ctl00_ArticleTopHeader_SectionLink" href="http://www.codeproject.com/KB/architecture/">Design and Architecture</a> »
	<a id="ctl00_ArticleTopHeader_SubsectionLink" href="http://www.codeproject.com/KB/architecture/index.aspx?#Design%20and%20Architecture%20-%20General">General</a>
	
	<span id="ctl00_ArticleTopHeader_SkillLevel" class="ArticleAdvanced">&nbsp;&nbsp;&nbsp; Advanced</span> 
	<span id="ctl00_ArticleTopHeader_LicenceTerms" class="SmallText" style="margin-left: 40px;">License: <a href="http://www.codeproject.com/info/cpol10.aspx">The Code Project Open License (CPOL)</a></span>
	<br>
	<br>
	<h1><span id="ctl00_ArticleTopHeader_ArticleTitle" class="ArticleTopTitle">NHibernate Best Practices with ASP.NET, 1.2nd Ed.</span></h1>
	
		<b>By <a href="http://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=2797038">Billy McCafferty</a></b><br>
	
	<br>
    <span id="ctl00_ArticleTopHeader_ArticleDescr">This article describes best practices for leveraging the benefits of NHibernate 1.2, ASP.NET, generics and unit testing together.</span>
</td>
		<td style="width: 210px;">
	<span id="ctl00_ArticleTopHeader_ArticleAttributes" class="SmallText">C#, Windows, .NET, ASP.NET, Visual-Studio, WebForms, SQL2000, DBA, Dev</span>
	<table style="margin: 8px 0pt 0pt; padding: 0pt;" class="SmallText">
	
	<tbody><tr><td>Posted:</td><td><b>11 Mar 2006</b></td></tr>
	
	<tr><td>Updated:</td><td><b>11 Jun 2008</b></td></tr>
	
	<tr><td>Views:</td><td><b>994,821</b></td></tr>
	
	<tr><td>Bookmarked:</td><td><b>805 times</b></td></tr>
	
	
	
	
	</tbody></table>
</td>
	</tr>
</tbody></table>

	</div>
</div>

<div>

<div id="ctl00_LHNavBar" class="LHNavBar">

	

<div class="announce-header">Announcements</div>
<div class="announce-content">
<table cellpadding="2">










<tbody><tr valign="middle"><td><img src="vsx_24.gif" alt="Comp" align="middle" height="24px" width="24px"></td>
<td><a href="http://www.codeproject.com/Competitions/376/Visual-Studio-Extension.aspx">Build a VS2010 addin win a Zune</a></td></tr>



<tr valign="middle"><td><img src="app_24.jpg" alt="Comp" align="middle" height="24px" width="24px"></td>
<td><a href="http://www.codeproject.com/Competitions/370/Windows-7-Contest.aspx">Windows 7 Comp<br>Win a laptop!</a></td></tr>


<tr valign="middle"><td><img src="monthlycomp.png" alt="Comp" align="middle" height="24px" width="24px"></td>
<td><a id="ctl00_Announcements_CompLink" href="http://www.codeproject.com/Feature/ArticleCompetition/">Monthly Competition</a></td></tr>
</tbody></table>
</div>
		
	
<div id="Th">
</div>

	
	
	<div id="SectionMenu">
<div class="MenuCat">Articles</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Content/Chapter.aspx?chptId=1" onclick="return ToggleMenu('Chapter1');">Desktop Development</a></div>
<div class="MenuSectionBlock" id="Chapter1" style="display: none;">
<div class="MI" id="Section1"><a href="http://www.codeproject.com/KB/buttons/">Button Controls</a></div>
<div class="MI" id="Section15"><a href="http://www.codeproject.com/KB/clipboard/">Clipboard</a></div>
<div class="MI" id="Section2"><a href="http://www.codeproject.com/KB/combobox/">Combo &amp; List Boxes</a></div>
<div class="MI" id="Section67"><a href="http://www.codeproject.com/KB/dialog/">Dialogs and Windows</a></div>
<div class="MI" id="Section107"><a href="http://www.codeproject.com/KB/gadgets/">Desktop Gadgets</a></div>
<div class="MI" id="Section16"><a href="http://www.codeproject.com/KB/docview/">Document / View</a></div>
<div class="MI" id="Section4"><a href="http://www.codeproject.com/KB/edit/">Edit Controls</a></div>
<div class="MI" id="Section17"><a href="http://www.codeproject.com/KB/files/">Files and Folders</a></div>
<div class="MI" id="Section3"><a href="http://www.codeproject.com/KB/grid/">Grid &amp; Data Controls</a></div>
<div class="MI" id="Section5"><a href="http://www.codeproject.com/KB/list/">List Controls</a></div>
<div class="MI" id="Section6"><a href="http://www.codeproject.com/KB/menus/">Menus</a></div>
<div class="MI" id="Section14"><a href="http://www.codeproject.com/KB/miscctrl/">Miscellaneous</a></div>
<div class="MI" id="Section18"><a href="http://www.codeproject.com/KB/printing/">Printing</a></div>
<div class="MI" id="Section95"><a href="http://www.codeproject.com/KB/progress/">Progress Controls</a></div>
<div class="MI" id="Section11"><a href="http://www.codeproject.com/KB/selection/">Selection Controls</a></div>
<div class="MI" id="Section19"><a href="http://www.codeproject.com/KB/shell/">Shell and IE programming</a></div>
<div class="MI" id="Section68"><a href="http://www.codeproject.com/KB/smart/">Smart Client</a></div>
<div class="MI" id="Section8"><a href="http://www.codeproject.com/KB/splitter/">Splitter Windows</a></div>
<div class="MI" id="Section9"><a href="http://www.codeproject.com/KB/static/">Static &amp; Panel Controls</a></div>
<div class="MI" id="Section10"><a href="http://www.codeproject.com/KB/statusbar/">Status Bar</a></div>
<div class="MI" id="Section7"><a href="http://www.codeproject.com/KB/tabs/">Tabs &amp; Property Pages</a></div>
<div class="MI" id="Section12"><a href="http://www.codeproject.com/KB/toolbars/">Toolbars &amp; Docking windows</a></div>
<div class="MI" id="Section13"><a href="http://www.codeproject.com/KB/tree/">Tree Controls</a></div>
</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Content/Chapter.aspx?chptId=2" onclick="return ToggleMenu('Chapter2');">Web Development</a></div>
<div class="MenuSectionBlock" id="Chapter2" style="display: none;">
<div class="MI" id="Section70"><a href="http://www.codeproject.com/KB/ajax/">Ajax and Atlas</a></div>
<div class="MI" id="Section27"><a href="http://www.codeproject.com/KB/applications/">Applications &amp; Tools</a></div>
<div class="MI" id="Section85"><a href="http://www.codeproject.com/KB/asp/">ASP</a></div>
<div class="MI" id="Section89"><a href="http://www.codeproject.com/KB/aspnet/">ASP.NET</a></div>
<div class="MI" id="Section28"><a href="http://www.codeproject.com/KB/webforms/">ASP.NET Controls</a></div>
<div class="MI" id="Section38"><a href="http://www.codeproject.com/KB/ATL-Server/">ATL Server</a></div>
<div class="MI" id="Section29"><a href="http://www.codeproject.com/KB/web-cache/">Caching</a></div>
<div class="MI" id="Section91"><a href="http://www.codeproject.com/KB/web-image/">Charts, Graphs and Images</a></div>
<div class="MI" id="Section25"><a href="http://www.codeproject.com/KB/scripting/">Client side scripting</a></div>
<div class="MI" id="Section30"><a href="http://www.codeproject.com/KB/custom-controls/">Custom Controls</a></div>
<div class="MI" id="Section23"><a href="http://www.codeproject.com/KB/HTML/">HTML / CSS</a></div>
<div class="MI" id="Section24"><a href="http://www.codeproject.com/KB/ISAPI/">ISAPI</a></div>
<div class="MI" id="Section33"><a href="http://www.codeproject.com/KB/server-management/">Site &amp; Server Management</a></div>
<div class="MI" id="Section34"><a href="http://www.codeproject.com/KB/session/">Session State</a></div>
<div class="MI" id="Section113"><a href="http://www.codeproject.com/KB/silverlight/">Silverlight</a></div>
<div class="MI" id="Section36"><a href="http://www.codeproject.com/KB/trace/">Trace and Logs</a></div>
<div class="MI" id="Section31"><a href="http://www.codeproject.com/KB/user-controls/">User Controls</a></div>
<div class="MI" id="Section37"><a href="http://www.codeproject.com/KB/validation/">Validation</a></div>
<div class="MI" id="Section35"><a href="http://www.codeproject.com/KB/viewstate/">View State</a></div>
<div class="MI" id="Section26"><a href="http://www.codeproject.com/KB/WAP/">WAP / WML</a></div>
<div class="MI" id="Section32"><a href="http://www.codeproject.com/KB/web-security/">Web Security</a></div>
<div class="MI" id="Section20"><a href="http://www.codeproject.com/KB/webservices/">Web Services</a></div>
<div class="MI" id="Section144"><a href="http://www.codeproject.com/KB/PHP/">PHP</a></div>
</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Content/Chapter.aspx?chptId=9" onclick="return ToggleMenu('Chapter9');">Enterprise Systems</a></div>
<div class="MenuSectionBlock" id="Chapter9" style="display: none;">
<div class="MI" id="Section98"><a href="http://www.codeproject.com/KB/MCMS/">Content Management Server</a></div>
<div class="MI" id="Section99"><a href="http://www.codeproject.com/KB/biztalk/">Microsoft BizTalk Server</a></div>
<div class="MI" id="Section102"><a href="http://www.codeproject.com/KB/exchange/">Microsoft Exchange</a></div>
<div class="MI" id="Section90"><a href="http://www.codeproject.com/KB/office/">Office Development</a></div>
<div class="MI" id="Section101"><a href="http://www.codeproject.com/KB/sharepoint/">SharePoint Server</a></div>
</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Content/Chapter.aspx?chptId=3" onclick="return ToggleMenu('Chapter3');">Multimedia</a></div>
<div class="MenuSectionBlock" id="Chapter3" style="display: none;">
<div class="MI" id="Section42"><a href="http://www.codeproject.com/KB/audio-video/">Audio and Video</a></div>
<div class="MI" id="Section44"><a href="http://www.codeproject.com/KB/directx/">DirectX</a></div>
<div class="MI" id="Section46"><a href="http://www.codeproject.com/KB/GDI/">GDI</a></div>
<div class="MI" id="Section47"><a href="http://www.codeproject.com/KB/GDI-plus/">GDI+</a></div>
<div class="MI" id="Section43"><a href="http://www.codeproject.com/KB/graphics/">General Graphics</a></div>
<div class="MI" id="Section45"><a href="http://www.codeproject.com/KB/openGL/">OpenGL</a></div>
</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Content/Chapter.aspx?chptId=4" onclick="return ToggleMenu('Chapter4');">Database</a></div>
<div class="MenuSectionBlock" id="Chapter4" style="display: none;">
<div class="MI" id="Section66"><a href="http://www.codeproject.com/KB/database/">Database</a></div>
<div class="MI" id="Section100"><a href="http://www.codeproject.com/KB/reporting-services/">SQL Reporting Services</a></div>
</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Content/Chapter.aspx?chptId=8" onclick="return ToggleMenu('Chapter8');">Platforms, Frameworks &amp; Libraries</a></div>
<div class="MenuSectionBlock" id="Chapter8" style="display: none;">
<div class="MI" id="Section83"><a href="http://www.codeproject.com/KB/atl/">ATL</a></div>
<div class="MI" id="Section117"><a href="http://www.codeproject.com/KB/MFC/">MFC</a></div>
<div class="MI" id="Section88"><a href="http://www.codeproject.com/KB/stl/">STL</a></div>
<div class="MI" id="Section84"><a href="http://www.codeproject.com/KB/wtl/">WTL</a></div>
<div class="MI" id="Section49"><a href="http://www.codeproject.com/KB/COM/">COM / COM+</a></div>
<div class="MI" id="Section76"><a href="http://www.codeproject.com/KB/dotnet/">.NET Framework</a></div>
<div class="MI" id="Section92"><a href="http://www.codeproject.com/KB/winsdk/">Win32/64 SDK &amp; OS</a></div>
<div class="MI" id="Section108"><a href="http://www.codeproject.com/KB/vista/">Vista API</a></div>
<div class="MI" id="Section110"><a href="http://www.codeproject.com/KB/vista-security/">Vista Security</a></div>
<div class="MI" id="Section82"><a href="http://www.codeproject.com/KB/cross-platform/">Cross Platform</a></div>
<div class="MI" id="Section69"><a href="http://www.codeproject.com/KB/game/">Game Development</a></div>
<div class="MI" id="Section73"><a href="http://www.codeproject.com/KB/mobile/">Mobile Development</a></div>
<div class="MI" id="Section106"><a href="http://www.codeproject.com/KB/WC/">Windows CardSpace</a></div>
<div class="MI" id="Section103"><a href="http://www.codeproject.com/KB/WCF/">Windows Communication Foundation</a></div>
<div class="MI" id="Section104"><a href="http://www.codeproject.com/KB/WPF/">Windows Presentation Foundation</a></div>
<div class="MI" id="Section105"><a href="http://www.codeproject.com/KB/WF/">Windows Workflow Foundation</a></div>
<div class="MI" id="Section119"><a href="http://www.codeproject.com/KB/library/">Libraries</a></div>
<div class="MI" id="Section122"><a href="http://www.codeproject.com/KB/powershell/">Windows Powershell</a></div>
<div class="MI" id="Section123"><a href="http://www.codeproject.com/KB/linq/">LINQ</a></div>
</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Content/Chapter.aspx?chptId=5" onclick="return ToggleMenu('Chapter5');">Languages</a></div>
<div class="MenuSectionBlock" id="Chapter5" style="display: none;">
<div class="MI" id="Section71"><a href="http://www.codeproject.com/KB/cpp/">C / C++ Language</a></div>
<div class="MI" id="Section72"><a href="http://www.codeproject.com/KB/mcpp/">C++ / CLI</a></div>
<div class="MI" id="Section93"><a href="http://www.codeproject.com/KB/cs/">C#</a></div>
<div class="MI" id="Section78"><a href="http://www.codeproject.com/KB/msil/">MSIL</a></div>
<div class="MI" id="Section86"><a href="http://www.codeproject.com/KB/vbscript/">VBScript</a></div>
<div class="MI" id="Section87"><a href="http://www.codeproject.com/KB/vb/">VB.NET</a></div>
<div class="MI" id="Section115"><a href="http://www.codeproject.com/KB/vb-interop/">VB6 Interop</a></div>
<div class="MI" id="Section77"><a href="http://www.codeproject.com/KB/net-languages/">Other .NET Languages</a></div>
<div class="MI" id="Section21"><a href="http://www.codeproject.com/KB/XML/">XML</a></div>
<div class="MI" id="Section96"><a href="http://www.codeproject.com/KB/java/">Java</a></div>
</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Content/Chapter.aspx?chptId=6" onclick="return ToggleMenu('Chapter6');">General Programming</a></div>
<div class="MenuSectionBlock" id="Chapter6" style="display: none;">
<div class="MI" id="Section57"><a href="http://www.codeproject.com/KB/recipes/">Algorithms &amp; Recipes</a></div>
<div class="MI" id="Section64"><a href="http://www.codeproject.com/KB/bugs/">Bugs &amp; Workarounds</a></div>
<div class="MI" id="Section79"><a href="http://www.codeproject.com/KB/collections/">Collections</a></div>
<div class="MI" id="Section56"><a href="http://www.codeproject.com/KB/security/">Cryptography &amp; Security</a></div>
<div class="MI" id="Section50"><a href="http://www.codeproject.com/KB/datetime/">Date and Time</a></div>
<div class="MI" id="Section52"><a href="http://www.codeproject.com/KB/DLL/">DLLs &amp; Assemblies</a></div>
<div class="MI" id="Section80"><a href="http://www.codeproject.com/KB/exception/">Exception Handling</a></div>
<div class="MI" id="Section81"><a href="http://www.codeproject.com/KB/locale/">Localisation</a></div>
<div class="MI" id="Section53"><a href="http://www.codeproject.com/KB/macros/">Macros and Add-ins</a></div>
<div class="MI" id="Section54"><a href="http://www.codeproject.com/KB/tips/">Programming Tips</a></div>
<div class="MI" id="Section55"><a href="http://www.codeproject.com/KB/string/">String handling</a></div>
<div class="MI" id="Section22"><a href="http://www.codeproject.com/KB/IP/">Internet / Network</a></div>
<div class="MI" id="Section58"><a href="http://www.codeproject.com/KB/threads/">Threads, Processes &amp; IPC</a></div>
<div class="MI" id="Section59"><a href="http://www.codeproject.com/KB/winhelp/">WinHelp / HTMLHelp</a></div>
<div class="MI" id="Section141"><a href="http://www.codeproject.com/KB/answers/">Uncategorised Quick Answers</a></div>
</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Content/Chapter.aspx?chptId=10" onclick="return ToggleMenu('Chapter10');">Graphics / Design</a></div>
<div class="MenuSectionBlock" id="Chapter10" style="display: none;">
<div class="MI" id="Section40"><a href="http://www.codeproject.com/KB/expression/">Expression</a></div>
<div class="MI" id="Section114"><a href="http://www.codeproject.com/KB/usability/">Usability</a></div>
</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Content/Chapter.aspx?chptId=11" onclick="return ToggleMenu('Chapter11');">Development Lifecycle</a></div>
<div class="MenuSectionBlock" id="Chapter11">
<div class="MI" id="Section51"><a href="http://www.codeproject.com/KB/debug/">Debug Tips</a></div>
<div class="MIS" id="Section39"><a href="http://www.codeproject.com/KB/architecture/">Design and Architecture</a></div>
<div class="MI" id="Section112"><a href="http://www.codeproject.com/KB/install/">Installation</a></div>
<div class="MI" id="Section41"><a href="http://www.codeproject.com/KB/work/">Work Issues</a></div>
<div class="MI" id="Section128"><a href="http://www.codeproject.com/KB/testing/">Testing and QA</a></div>
<div class="MI" id="Section126"><a href="http://www.codeproject.com/KB/codegen/">Code Generation</a></div>
</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Content/Chapter.aspx?chptId=7" onclick="return ToggleMenu('Chapter7');">General Reading</a></div>
<div class="MenuSectionBlock" id="Chapter7" style="display: none;">
<div class="MI" id="Section60"><a href="http://www.codeproject.com/KB/books/">Book Chapters</a></div>
<div class="MI" id="Section61"><a href="http://www.codeproject.com/KB/book-reviews/">Book Reviews</a></div>
<div class="MI" id="Section109"><a href="http://www.codeproject.com/KB/hardware-review/">Hardware Reviews</a></div>
<div class="MI" id="Section63"><a href="http://www.codeproject.com/KB/interviews/">Interviews</a></div>
<div class="MI" id="Section62"><a href="http://www.codeproject.com/KB/scrapbook/">Scrapbook</a></div>
<div class="MI" id="Section48"><a href="http://www.codeproject.com/KB/system/">Hardware &amp; System</a></div>
<div class="MI" id="Section136"><a href="http://www.codeproject.com/KB/Blogs/">Uncategorised Technical Blogs</a></div>
<div class="MI" id="Section140"><a href="http://www.codeproject.com/KB/mentor/">Author Resources</a></div>
</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Content/Chapter.aspx?chptId=12" onclick="return ToggleMenu('Chapter12');">Third Party Products</a></div>
<div class="MenuSectionBlock" id="Chapter12" style="display: none;">
<div class="MI" id="Section65"><a href="http://www.codeproject.com/KB/showcase/">Product Showcase</a></div>
<div class="MI" id="Section124"><a href="http://www.codeproject.com/KB/solution-center/">Solution Center</a></div>
</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Content/Chapter.aspx?chptId=13" onclick="return ToggleMenu('Chapter13');">Mentor Resources</a></div>
<div class="MenuSectionBlock" id="Chapter13" style="display: none;">
</div>
</div>
<div style="margin-top: 5px;"></div>
<div class="MenuCat">Services</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Catalog/List.aspx">Product Catalog</a></div>
<div class="MenuChapter"><a href="http://www.codeproject.com/services/certificates/index.aspx">Code-signing Certificates</a></div>
<div class="MenuChapter"><a href="http://www.codeproject.com/script/Jobs/List.aspx">Job Board</a></div>
<div class="MenuChapter"><a href="http://www.codeproject.com/Services/Addins/">CodeProject VS2008 Addin</a></div>
<div style="margin-top: 5px;"></div>
<div class="MenuCat">Feature Zones</div>
<div class="MenuChapter"><a href="http://www.codeproject.com/kb/Showcase/">Product Showcase</a></div>
<div class="MenuChapter"><a href="http://www.codeproject.com/Zones/WhitePapers/">WhitePapers / Webcasts</a></div>
<div class="MenuChapter"><a href="http://www.codeproject.com/Redir.aspx?adid=12879&amp;obid=0&amp;obtid=0">ASP.NET Web Hosting</a></div>
<div style="margin-top: 5px;"></div>


	<div style="margin: auto; width: 150px;"><a href="http://www.codeproject.com/Redir.aspx?adid=12743&amp;obid=13390&amp;obtid=2&amp;way=ban" target="_top" rel="nofollow"><img src="serveimg.aspx" alt="" border="0" height="80px" width="150px"></a>
	</div>
	
	<div style="margin: 10px auto auto; width: 160px;"><a href="http://www.codeproject.com/Redir.aspx?adid=12920&amp;obid=13390&amp;obtid=2&amp;way=ban" target="_top" rel="nofollow"><img src="serveimg_001.aspx" alt="" border="0" height="600px" width="160px"></a>
	</div>
</div>

<div id="ctl00_ArticlePane" class="ArticlePane LeftColumn">

	
<table class="SearchHeaderBar" cellspacing="0" width="100%">
<tbody><tr>
<td width="100%">&nbsp;</td>
<td style="white-space: nowrap; width: 60%;" align="right" valign="middle">
	<form method="get" action="http://www.codeproject.com/info/search.aspx" name="Search" style="margin: 0pt;">
	<b>Search &nbsp;</b>
	<input value="" class="SmallText" name="artkw" style="width: 200px;">
	<select class="SmallText offblack" style="font-weight: bold;" name="sbo">
	<option value="kw" selected="true">Articles / Quick Answers</option>
<option value="fm">Messages</option>
<option value="s">Jobs</option>
<option value="ctlk">Product Catalog</option>

	</select>
	<input class="SmallText" style="font-weight: bold;" value=" Go! " type="submit"> &nbsp;
	</form>
</td>
<td class="TinyText" style="white-space: nowrap;">
	
	<a href="http://www.codeproject.com/info/search.aspx">Advanced Search</a><br>
	
	
	<a id="ctl00_SearchBarCtrl_AddToIESearchLnk" href="http://www.codeproject.com/">Add to IE Search</a>
</td>
</tr>
</tbody></table>

	<a name="Main"></a>
	<span id="ctl00_ResultMessage"></span>
	
	
    
	<div id="ctl00_ArtDiv">
	<table border="0" cellpadding="0" cellspacing="0">	
	<tbody><tr valign="top">
		<td valign="top" width="100%">
		    
<table>

<tbody><tr><td class="SmallText"><img id="ctl00_ArticleAwards_AR_ctl01_AI" src="prize_winner.gif" style="border-width: 0px;"></td> 
<td class="SmallText" style="white-space: nowrap;">Prize winner in Competition 
"ASP.NET Feb 2006" <i></i></td></tr>

</tbody></table>



			
<div class="SmallText">
<img src="print.gif" alt="print" style="vertical-align: middle;" height="16px" width="16px"><a id="ctl00_ArticleHeaderLinks_PrintLnk" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?display=Print">Print</a> &nbsp;
	


<span id="SBI"><img src="add.gif" id="ctl00_ArticleHeaderLinks_AddTo_Img" alt="add" style="vertical-align: middle;" height="16" width="16">
<a href="#">Share</a></span>
<div style="left: 197.5px; top: 358.6px;" id="ATD"><div><a class="AddTo" title="Add this page to Digg" onclick="return socialLinks.addto(0);" href="#"><img src="addto_digg.png" align="absmiddle" border="0" height="16px" width="16px"> Digg</a> </div><div><a class="AddTo" title="Add this page to Del.icio.us" onclick="return socialLinks.addto(1);" href="#"><img src="addto_delicious.png" align="absmiddle" border="0" height="16px" width="16px"> Del.icio.us</a> </div><div><a class="AddTo" title="Add this page to Google" onclick="return socialLinks.addto(2);" href="#"><img src="addto_google.png" align="absmiddle" border="0" height="16px" width="16px"> Google</a> </div><div><a class="AddTo" title="Add this page to Windows Live" onclick="return socialLinks.addto(3);" href="#"><img src="addto_live.png" align="absmiddle" border="0" height="16px" width="16px"> Windows Live</a> </div><div><a class="AddTo" title="Add this page to Technorati" onclick="return socialLinks.addto(4);" href="#"><img src="addto_technorati.png" align="absmiddle" border="0" height="16px" width="16px"> Technorati</a> </div><div><a class="AddTo" title="Add this page to Blink" onclick="return socialLinks.addto(5);" href="#"><img src="addto_blink.png" align="absmiddle" border="0" height="16px" width="16px"> Blink</a> </div><div><a class="AddTo" title="Add this page to Facebook" onclick="return socialLinks.addto(6);" href="#"><img src="addto_facebook.png" align="absmiddle" border="0" height="16px" width="16px"> Facebook</a> </div><div><a class="AddTo" title="Add this page to Furl" onclick="return socialLinks.addto(7);" href="#"><img src="addto_furl.png" align="absmiddle" border="0" height="16px" width="16px"> Furl</a> </div><div><a class="AddTo" title="Add this page to Simpy" onclick="return socialLinks.addto(8);" href="#"><img src="addto_simpy.png" align="absmiddle" border="0" height="16px" width="16px"> Simpy</a> </div><div><a class="AddTo" title="Add this page to Reddit" onclick="return socialLinks.addto(9);" href="#"><img src="addto_reddit.png" align="absmiddle" border="0" height="16px" width="16px"> Reddit</a> </div><div><a class="AddTo" title="Add this page to Newsvine" onclick="return socialLinks.addto(10);" href="#"><img src="addto_newsvine.png" align="absmiddle" border="0" height="16px" width="16px"> Newsvine</a> </div><div><a class="AddTo" title="Add this page to Stumbleupon" onclick="return socialLinks.addto(11);" href="#"><img src="addto_stumbleupon.png" align="absmiddle" border="0" height="16px" width="16px"> Stumbleupon</a> </div><div><a class="AddTo" title="Add this page to Mr. Wong" onclick="return socialLinks.addto(12);" href="#"><img src="addto_mrwong.png" align="absmiddle" border="0" height="16px" width="16px"> Mr. Wong</a> </div><div><a class="AddTo" title="Send as Email" onclick="return socialLinks.addto(13);" href="#"><img src="envelope.gif" align="absmiddle" border="0" height="16px" width="16px"> Send as Email</a> </div></div>
 &nbsp;
 &nbsp;
 &nbsp;
<img src="discuss.gif" alt="Discuss" style="vertical-align: middle;" height="16px" width="15px"> <a href="#_comments">Discuss</a> &nbsp; 

<img src="report.gif" alt="Broken Article?" style="vertical-align: middle;" height="16px" width="16px"><a id="ctl00_ArticleHeaderLinks_BrokenLnk" href="http://www.codeproject.com/script/Articles/Report.aspx?aid=13390">Report</a> &nbsp;
</div>
		</td>
		<td style="text-align: right; white-space: nowrap; width: 100px;">
		<table id="ctl00_CurRat" name="CurRat_13390">
	<tbody><tr>
		<td>
<table>
<tbody><tr>
	<td id="ctl00_ArticleRating_VL" style="white-space: nowrap;" class="SmallText" align="right"> 
		<span id="ctl00_ArticleRating_VoteLabel">289 votes for this article.</span>
	</td>
		
	<td>
		<table border="1" cellpadding="0" cellspacing="0">
			<tbody><tr>
				<td align="left" bgcolor="White" height="7px" width="20px"><img src="red.gif" align="middle" border="0" height="7" width="20"></td>
				<td align="left" bgcolor="White" height="7px" width="20px"><img src="red.gif" align="middle" border="0" height="7" width="20"></td>
				<td align="left" bgcolor="White" height="7px" width="20px"><img src="red.gif" align="middle" border="0" height="7" width="20"></td>
				<td align="left" bgcolor="White" height="7px" width="20px"><img src="red.gif" align="middle" border="0" height="7" width="20"></td>
				<td style="padding: 0px; white-space: nowrap;" align="left" bgcolor="White" height="7px" width="20px"><img src="red.gif" align="middle" border="0" height="7" width="17"><img src="white.gif" align="middle" border="0" height="7" width="3"></td>
			</tr>
		</tbody></table>
		
		<span id="ctl00_ArticleRating_Votes" class="SmallText"></span>
	</td>
</tr>
<tr id="ctl00_ArticleRating_PopularityRow">
			<td colspan="2" class="SmallText" align="right">
		<a id="ctl00_ArticleRating_PopularityLnk" title="Calculated as rating x Log10(# votes)" href="http://www.codeproject.com/script/Articles/TopArticles.aspx?ta_so=1">Popularity: 11.99</a>
		<span id="ctl00_ArticleRating_PopularityLbl"></span>
		<span id="ratingVal">Rating: <b>4.87</b> out of 5</span>
		
	</td>
		</tr>
		
</tbody></table>
</td>
		<td>            
<div>
<table class="HistTable" title="Voting Distribution. Recent data only"><tbody><tr><td><img src="pollcol.gif" alt="6 votes, 2.1%" title="6 votes, 2.1%" border="0px" height="1px" width="10px"><br>1</td>
<td><img src="pollcol.gif" alt="1 vote, 0.3%" title="1 vote, 0.3%" border="0px" height="1px" width="10px"><br>2</td>
<td><img src="pollcol.gif" alt="6 votes, 2.1%" title="6 votes, 2.1%" border="0px" height="1px" width="10px"><br>3</td>
<td><img src="pollcol.gif" alt="13 votes, 4.5%" title="13 votes, 4.5%" border="0px" height="1px" width="10px"><br>4</td>
<td><img src="pollcol.gif" alt="260 votes, 90.9%" title="260 votes, 90.9%" border="0px" height="20px" width="10px"><br>5</td>
</tr></tbody></table>
</div>



</td>
	</tr>
</tbody></table>

		</td>
	</tr>
	</tbody></table>
	
	
	
	

	
	

	
	
	
	
	
	
	
	
	
	
	
	
	<div id="contentdiv">
	
	<!-- Main Page Contents Start -->
	

<!-- Article Starts -->


<ul class="download">
<li><a href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices/BasicSample.zip">Download Basic NHibernate Sample - 1,477.9 KB</a> </li>

<li><a href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices/EnterpriseSample.zip">Download "Enterprise" NHibernate Sample - 2,168.9 KB</a> </li>
</ul>

<h2>Author's note added June 11, 2008 - Announcement of S#arp Architecture</h2>

<p>Thankfully, technologies evolve over the years. Accordingly, Microsoft has introduced ASP.NET MVC as an alternative to classic ASP.NET. I have developed a new architecture which uses many of the design principles of this article for this newer platform called <a href="http://devlicio.us/blogs/billy_mccafferty/archive/2008/04/21/asp-net-mvc-best-practices-with-nhibernate-and-spring-net.aspx">S#arp Architecture</a>. Although this article is still the recommended background reading material for S#arp Architecture, you'll find the new architecture to be simpler and more maintainable while still leveraging the best of what NHibernate has to offer.</p>

<h2>Preface to the 1.2<sup>nd</sup> Edition</h2>

<p>In March of 2006 I published my initial thoughts on NHibernate best practices with ASP.NET, generics and unit tests. I've been delighted to learn that these ideas have been implemented in a number of real-world scenarios with strong success. Since then, I've worked with many people to refine these ideas, learn from mistakes and leverage a more powerful version of NHibernate. Accordingly, although only a modest, yet important, amount of modification has been made to the underlying architecture, some other important factors have been updated and addressed in this article: </p>

<ul>
<li>Quite simply, NHibernate is awesome. In the previous edition of this article, I assumed you already knew this...but I now try to convince the dissenters as well. </li>

<li>NHibernate 1.2 natively supports generics. </li>

<li>NHibernate 1.2 natively supports nullable types. </li>

<li>NHibernate 1.2 natively supports mapping attributes. </li>

<li>NHibernate 1.2 can communicate with stored procedures. </li>

<li>Using CallContext for ISession storage in ASP.NET was susceptible to failure under load. </li>

<li>Exposing a publicly settable ID property created a point-of-susceptibility. </li>

<li>Providing automatic parent/child wiring, via Ayende's very helpful NHibernate.Generics, was <a href="http://www.ayende.com/Blog/archive/2006/10/16/7179.aspx">more headache than help</a>. </li>

<li>Have you used Rhino Mocks 3.0, NUnitAsp, or Fit? Well, these are all discussed with an expanded emphasis on test-driven development. </li>

<li>As an alternative to my recommendations, also consider <a href="http://www.castleproject.org/">Castle Project's offerings</a> such as <a href="http://www.castleproject.org/monorail/index.html">MonoRail</a> and/or <a href="http://www.castleproject.org/activerecord/index.html">ActiveRecord</a> for a simple yet powerful out-of-the-box framework for ASP.NET. In fact, if it's technically feasible and you can generate buy-in on your team for these off-the-shelf tools, I would recommend using them over a ground-up solution. But even if you do use Castle Project facilities, this article should still have a lot of useful information for you! </li>

<li>In addition to those listed above, there are other important refactorings and fixes throughout the article and the code. This edition is by no means just a light touch-up of the original article. </li>

<li>In addition to an overhaul of the original sample code, an expanded "enterprise" sample has been included demonstrating: 
<ul>
<li>NHibernate with web services </li>

<li>NHibernate with multiple databases </li>

<li>Integration with <a href="http://www.castleproject.org/container/index.html">Castle Windsor</a> </li>

<li>A reusable data layer for the data access components. </li>

<li>A simple example of Model-View-Presenter </li>
</ul>
</li>
</ul>

<p>A quick thanks goes out to those who have implemented my ideas in their own work and have given plenty of ideas for improvement and consideration! Now onto the 1.2<sup>nd</sup> edition... </p>

<h2>Article Contents</h2>

<ul>
<li><a href="#INTRODUCTION">Introduction</a> 
<ul>
<li><a href="#WHY_NHIBERNATE">Why Use an ORM?</a> </li>

<li><a href="#GOALS">Goals and Overview of Article</a> </li>
</ul>
</li>

<li><a href="#SAMPLE_APPS">Running the Sample Applications</a> </li>

<li><a href="#BASICS">NHibernate Integration Basics</a> 
<ul>
<li><a href="#BASIC_ARCH">Architectural Notes</a> </li>

<li><a href="#BASIC_APP">The Basic Sample Application</a> </li>

<li><a href="#TESTS">BasicSample.Tests with NUnit, NUnitAsp, Rhino Mocks and Fit</a> </li>

<li><a href="#CORE">BasicSample.Core for Defining the Domain Layer</a> </li>

<li><a href="#DATA">BasicSample.Data for Implementing NHibernate Communications</a> </li>

<li><a href="#WEB">BasicSample.Web for Tying it all Together</a> </li>
</ul>
</li>

<li><a href="#EXTENDING_BASICS">Extending the Basics to an "Enterprise" Solution</a> 
<ul>
<li><a href="#ENTERPRISE_ARCH">Real-World Architecture</a> </li>

<li><a href="#BEYOND_BASICS">Beyond the Basics</a> </li>
</ul>
</li>

<li><a href="#WHAT_NEXT">Where to go from here?</a> </li>

<li><a href="#MIGRATING">Migrating from NHibernate 1.0x to 1.2</a> </li>

<li><a href="#SUMMARY">Summary of NHibernate/ASP.NET Best Practices</a> </li>
</ul>
<a name="INTRODUCTION"></a>
<h2>Introduction</h2>
<a name="WHY_NHIBERNATE"></a>
<h3>Why Use an ORM?</h3>

<p>[Author's Note: The following is an excerpt taken from a book I tinker with in my "spare" time.]</p>

<p>"As we look to the horizon of a decade hence, we see no silver bullet. There is no single development, in either technology or management technique, which by itself promises even one order-of-magnitude improvement within a decade in productivity, in reliability, in simplicity." </p>

<p>These prophetic words were put forth by Frederick Brooks' in his now legendary paper, <a href="http://en.wikipedia.org/wiki/No_Silver_Bullet">No Silver Bullet</a>, in 1986. Heeding Brooks' words to a tee, it wasn't until more than a decade later, in 1997, that the software world was presented with a hint of an upcoming silver bullet in the form of NeXT's Enterprise Object Framework...one of the first object-relational mappers (ORM). Although not regularly conspicuously stated – often to avoid being seen as a heretic of software dogma – it is commonly accepted by many that ORM technologies, when used correctly, are, in fact, a silver bullet for software development. With the maturation of NHibernate, the ORM silver bullet has been formally introduced to the world of .NET. </p>

<p>The most common dissenters of ORM technologies, in general, are developers using Microsoft technologies. (As I've placed myself squarely into this realm for the past decade or so, I feel quite comfortable bringing us up first!) There seems to be an unwritten rule that "if it wasn't invented by Microsoft, then wait until Microsoft puts out the <em>right</em> way to do it." Stepping up to the plate, Microsoft intends to do just that with "LINQ to Entities" in the upcoming C# 3.0. (Yes, officially discard the use of "ObjectSpaces" and "DLINQ.") Developers may continue to wait for this technology or, alternatively, start realizing the benefits of ORM immediately. To be fair, the not-invented-by-Microsoft toolset for .NET developers used to be sparse but has been steadily growing since the advent of .NET. Circa 2004, the "not created by the mothership" toolset of open source tools finally began to reach a respectable level of maturity and should be seriously considered for any .NET endeavor. (And since, statistically, the majority of software projects fail, it sounds like the consideration of an expanded toolset is certainly warranted.) The impending introduction of LINQ certainly brings great benefits to flexible querying. Fortunately, LINQ is not exclusive to Microsoft data-access layers and <a href="http://ayende.com/Blog/archive/2007/03/16/Linq-for-NHibernate.aspx">LINQ for NHibernate</a> is already well underway by <a href="http://www.ayende.com/">Ayende Rahien</a>. </p>

<p>Other dissenters of these technologies suggest that ORMs kill application performance and only provide a significant improvement to productivity in the initial stages of development. Furthermore, the argument continues, is that the use of an ORM becomes a serious detriment to project success only later in the project, when issues of performance and maintainability begin to have a more noticeable effect. Three obvious retorts come to mind in response to these protests. </p>

<p>First and foremost, in support of ORMs, using a framework such as NHibernate increases <em>your</em> performance as a developer. If you can spend 90% less time (yes, I said "90% less time") on developing data access code, then quality time can be spent improving the domain model and tuning performance – assuming it becomes necessary. Furthermore, leveraging a simple profiling tool goes a long way towards implicating the 5% of code that's causing 95% of the performance bottleneck. And in the cases in which the data access layer <em>is</em> the bottleneck, simple adjustments can usually be made to reap substantial improvements. Incidentally, this is no different than when not using an ORM. (Be sure to check out Peter Weissbrod's <a href="http://www.codeproject.com/useritems/NHibernate_Perf.asp">introductory article to profiling NHibernate applications</a>.) And in the very few situations in which the ORM framework is the bottleneck and can't be adjusted for improvement, it's trivially simple to bypass the ORM altogether if the data access layer has been properly abstracted. </p>

<p>Secondly, NHibernate, specifically, provides an incredible amount of control over all aspects of data-loading behavior. This has positive effects on developer productivity, application scalability, and application stability. Caching is certainly available – but this is readily available in non-ORM solutions as well. Other out-of-the-box features include lazy loading, support for inheritance, declaration of immutable classes, loading of read-only properties, support for generics, stored procedures, blah blah blah. The point is that all these powerful features have been proven in real-world scenarios and, therefore, have removed many hours of developing, debugging and tweaking a custom data access layer. (And if you really feel the need to get into the code, that's just fine since NHibernate's an open source project.) </p>

<p>Finally, I would argue that those who feel that ORMs like NHibernate become maintenance headaches later in a project are working with a coding architecture that would inhibit the maintenance of <em>any</em> data access layer. Just because I've suggested that NHibernate is a silver bullet doesn't imply that it eliminates the need for proper application design. With the proper amount of judicious, architectural forethought, NHibernate is quite possibly the most maintainable solution for tying a .NET application to a database. </p>

<p>Needless to say, NHibernate, like other ORM tools, has alleviated the maintenance of thousands of lines of code and stored procedures, thus allowing developers to focus more attention on the core of a project: its domain model and business logic. Even if you automatically generate your ADO.NET data-access layer using a tool such as CodeSmith or LLBLGen Pro, NHibernate provides the flexibility in decoupling your domain model from your relational model. Your database should be an "implementation detail" that is defined to support your domain model, not the other way around. The remainder of this article focuses on describing best practices for integrating NHibernate into ASP.NET using well established design patterns and "lessons learned from the field".</p>
<a name="GOALS"></a>
<h3>Goals and Overview of Article</h3>

<p>This article assumes a good understanding of C# and NHibernate, knowledge of the Data Access Object / Repository pattern, and at least a basic familiarity with Generics. Note that this article does not focus on <em>using</em> NHibernate but, instead, on <em>integrating</em> NHibernate into ASP.NET applications. If you're just getting acquainted with NHibernate, I'd recommend reading these two great introductions at TheServerSide.net: <a href="http://www.theserverside.net/articles/showarticle.tss?id=NHibernate">Part 1</a> and <a href="http://www.theserverside.net/articles/showarticle.tss?id=NHibernateP2">Part 2</a>. (Also keep an eye out for Pierre Kuate's forthcoming <a href="http://www.manning.com/kuate/">NHibernate in Action</a>.) For an extensive overview of the Data Access Object pattern, which is leveraged heavily within the samples, go to <a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html">J2EE's BluePrints catalog</a>. Although I use the phrase "Data Access Object" (or "DAO") throughout, it is interchangeable with Eric Evans' "Repository" in <a href="http://www.infoq.com/minibooks/domain-driven-design-quickly">Domain-Driven Design</a>. I just find "DAO" more convenient to type!</p>

<p>In building solid data integration within an ASP.NET 2.0 application, we aim to achieve the following objectives:</p>

<ul>
<li>Presentation and domain layers should be in relative ignorance of how they communicate with the database. You should be able to modify your means of data communication with minimal modification to these layers. </li>

<li>Business logic should be easily testable without depending on a live database. </li>

<li>NHibernate features, such as lazy-loading, should be available throughout the entire ASPX page life-cycle. </li>

<li>.NET 2.0 Generics should be leveraged to alleviate duplicated code. </li>
</ul>

<p>Two sample applications have been included, demonstrating the use of NHibernate with ASP.NET while meeting the above objectives:</p>

<ul>
<li><a href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices/BasicSample.zip">Basic NHibernate Sample</a>: This sample demonstrates the fundamentals of using NHibernate with ASP.NET and unit tests with a simple-to-understand, but not completely reusable, architecture. </li>

<li><a href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices/EnterpriseSample.zip">"Enterprise" NHibernate Sample</a>: This sample is provided with an architecturally sound grounding using proven design patterns which should allow you to quickly reuse the framework in almost any sized ASP.NET project. This sample also serves to demonstrate NHibernate with ASP.NET and "a whole bunch of other stuff" including communicating with multiple databases, using the pattern <a href="http://www.codeproject.com/useritems/ModelViewPresenter.asp">Model-View-Presenter</a>, setting up a simple web-service which uses NHibernate, and integrating with <a href="http://www.castleproject.org/container/index.html">Castle Windsor</a>. Although code is included for communicating with multiple databases, a detailed explanation is beyond the scope of this article and may be found at the CodeProject.com article, <a href="http://www.codeproject.com/useritems/NHibernateMultipleDBs.asp">Using NHibernate with Multiple Databases</a>. (Note that that article's sample application is compatible with NHibernate 1.0x; albeit, the general approach is still applicable.) </li>
</ul>

<p>What follows now is a description of how each of the aforementioned design objectives has been tackled in the sample applications. But before getting into the implementation details, let's skip right to the chase and get the sample up and running. </p>
<a name="SAMPLE_APPS"></a>
<h2>Running the Basic NHibernate Sample</h2>

<p>The sample application, at the risk of being terribly cliché, utilize the Northwind database within SQL Server 2005 to view and update a listing of Northwind customers. To demonstrate the use of lazy-loading, the application also displays the orders that each customer has made. All you need to run the samples locally is IIS with the .NET 2.0 Framework installed, and SQL Server 2005 (or 2000) containing the Northwind database. (Since SQL Server 2005 doesn't come with Northwind by default, you can simply backup the Northwind DB from 2000 and restore it into 2005.) The samples also port to SQL Server 2000...simply modify the NHibernate configuration settings, accordingly.</p>

<p>To get the basic NHibernate sample application up and running:</p>

<ol>
<li>Unzip the sample application to the folder of your choice. </li>

<li>Create a new virtual directory within IIS. The alias should be <em>BasicNHibernateSample</em>, and the directory should point to the <em>BasicSample.Web</em> folder that was created after unzipping the application. </li>

<li>Open <em>BasicSample.Web/web.config</em> and <em>BasicSample.Tests/App.config</em> to modify the database connection strings to connect to a Northwind database on Microsoft SQL Server. </li>

<li>If, and only if, you're running IIS 7, modify web.config by commenting out the "compatible with IIS 6" section and uncomment the "compatible with IIS 7" section. </li>

<li>Open your web browser to <em><span><a href="http://localhost/BasicNHibernateSample/Default.aspx" class="smarterwiki-linkify">http://localhost/BasicNHibernateSample/Default.aspx</a></span></em>, and you're off and running! </li>
</ol>

<p>Steps for getting the "enterprise" sample up and running are discussed in <a href="#EXTENDING_BASICS">Extending the Basics to an "Enterprise" Solution</a>. But before that, now that you're able to follow along with the basic sample in front of you, we'll examine how the application was developed to meet our design objectives...</p>
<a name="BASICS"></a>
<h2>NHibernate Integration Basics</h2>

<p>When developing an application, my primary goals are to:</p>

<ul>
<li>Write code once and only once. </li>

<li>Focus on simplicity and readability. </li>

<li>Keep coupling and dependencies to a minimum. </li>

<li>Maintain a clean separation of concerns. </li>

<li>Do all of the above using test-driven development. </li>
</ul>

<p>This section discusses using these design principles for the integration of NHibernate into ASP.NET applications. We'll do this by dissecting the internals of the Basic NHibernate Sample. </p>
<a name="BASIC_ARCH"></a>
<h3>Architectural Notes</h3>

<p>The basic sample should not, necessarily, be seen as a reusable framework for your own ASP.NET application. The focus within this example application is on presenting NHibernate integration in a simple and concise manner. If you are looking for a "ready for the real-world" architecture, be sure to take a look at <a href="#EXTENDING_BASICS">Extending the Basics to an "Enterprise" Solution</a> after reviewing this section. With that said, the basic sample does present a number of best practice techniques and design patterns: </p>

<h4>Separated Interface</h4>

<p>Separated Interface, also known as Dependency Inversion, is a technique for establishing a clean separation of concerns between application tiers. This technique is <a href="http://www.martinfowler.com/eaaCatalog/separatedInterface.html">described by Martin Fowler</a>, <a href="http://www.objectmentor.com/resources/articles/dip.pdf">by Object Mentor</a>, and in further detail in Robert Martin's <a href="http://www.amazon.com/gp/product/0135974445/ref=pd_lpo_k2a_1_img/102-1170069-1054529?%5Fencoding=UTF8">Agile Software Development</a>. The technique is often used for cleanly separating a data access layer from a domain layer. For example, assume a Customer object - in the domain layer - needs to communicate with a data access object (DAO) to retrieve a number of past Orders. (Whether or not the domain layer should <em>ever</em> communicate directly with a DOA is left for another discussion.) Consequently, the Customer object has a dependency on the Order DAO - in the data layer. But for the Order DAO to return orders, the DAO requires a dependency back to the domain layer. </p>

<p>The simplest solution is to put the data layer, containing the DAOs, into the same physical assembly as the domain layer. To maintain a "virtual" separation of concerns, the containing project could include two folders, one named <em>Domain</em> and the other named <em>Data</em>. (I've actually used this approach on a good-sized project, in a former life, with regrettable consequences.) This approach brings with it a number of ill effects: </p>

<ul>
<li>The domain and data layers share a bi-directional dependency with each other. </li>

<li>There's nothing to prevent the data layer from bleeding into the domain layer and vice-versa. If it can't be structurally prevented then it <em>will</em> occur. </li>

<li>It's difficult to unit test the domain layer without using a live database to support the data layer. Among other drawbacks, this brings unit testing performance to a crawl; therefore, developers stop unit testing. </li>
</ul>

<p>Alternatively, the domain and data layers could be placed into physically separate assemblies; e.g., <em>Project.Core</em> and <em>Project.Data</em>, respectively. The domain layer (the <em>Project.Core</em> assembly) would contain domain objects and DAO <em>interfaces</em>. The data layer (the <em>Project.Data</em> assembly) would contain concrete implementations of the DAO interfaces defined in the domain layer. This is shown in the package diagram below. Note that the arrow signifies a uni-directional dependency from the data layer to the domain layer. </p>
<img alt="Screenshot - SeparatedInterface.jpg" src="separatedinterface.jpg" height="216" width="232"> 
<p>This clean separation brings with it a number of benefits: </p>

<ul>
<li>Developers are structurally unable to put concrete data-access code into the domain layer without adding a number of easy-to-spot references, such as to <em>NHibernate</em> or <em>System.Data.SqlClient</em>. </li>

<li>The domain layer remains in ignorant bliss of how the data layer communicates or with who it communicates. Therefore, it's easier to switch out the data-access implementation details (e.g., from ADO.NET to NHibernate) without having to modify the domain layer. </li>

<li>Having dependencies on interfaces makes it easy to provide a "mocked" data-access layer to the domain layer while unit testing. This keeps unit tests blazing fast and eliminates the need to maintain test data in the database. </li>
</ul>

<p>An implementation example of Separated Interface is included in the sample applications and is discussed further below. </p>

<h4>Dependency Injection</h4>

<p>Separated Interface, as described above, introduces a dilemma: how are the concrete DAO implementations given to the domain layer which only "knows" about interfaces? Dependency Injection, also known as Inversion of Control (IoC), describes the technique for doing this. With Dependency Injection, it's possible to remove many direct instantiations of concrete objects along with the inflexibility that comes along with calling the <code><span class="code-keyword">new</span></code> keyword directly. Dependency Injection may be performed manually or via an IoC Container. The manual approach is performed by simply passing an object's "service dependencies" to it via its constructor or via property setters. I've written an introduction to this approach within the CodeProject article, <a href="http://www.codeproject.com/cs/design/DependencyInjection.asp">Dependency Injection for Loose Coupling</a>. (Note that a "service dependency" may be a DAO, an emailing utility, or anything that leverages external, expensive, or shouldn't-be-used-in-unit-test resources.) This manual approach is most useful within unit tests because the explicitness of passing concrete dependencies is helpful in describing functionality. (Martin Fowler has some <a href="http://www.martinfowler.com/ieeeSoftware/explicit.pdf">wise words on the value of being explicit</a>.) Alternatively, dependency injection may be performed via an IoC Container driven by code or XML. (Fowler has also written a <a href="http://www.martinfowler.com/articles/injection.html">great introduction</a> to IoC Containers, service locators and making an appropriate choice between the two.) Think of IoC Containers as providing decoupling on steroids. The benefits of an IoC Container include a flexible, loosely-coupled framework and an increased emphasis on coding-to-interface. The drawback is an added layer of complexity within the application. This is one of the many trade-offs between flexibility and complexity which needs to be considered when developing an application. Here are two great tools for putting IoC Containers into practice:</p>

<ul>
<li><strong><a href="http://www.castleproject.org/container/index.html">Castle Windsor</a></strong>: The Castle Windsor, IoC Container provides great IoC support using a combination of XML configuration and strongly typed declarations. Some of the advantages Castle Windsor brings to the table are less XML and more compile-time error catching, when compared against other options. The <a href="http://www.castleproject.org/index.html">Castle Project</a> also has a number of other powerful modules, making it an attractive option if you're looking for more than just IoC. Wide support has been shown for this IoC Container which has generated a lot of buzz around the .NET development community. The <a href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices/EnterpriseSample.zip">"Enterprise" NHibernate Sample</a> includes an example of using Castle Windsor. </li>

<li><strong><a href="http://www.springframework.net/">Spring .NET</a></strong>: This framework provides IoC declared via XML configuration files. Like the Castle Project, Spring.NET also provides a wide assortment of additional development utilities. This option should be particularly attractive for developers coming from the Java world and are already familiar with the <a href="http://www.springframework.org/">Spring Framework</a>. </li>
</ul>

<p>I've found that using an IoC Container is most useful outside of unit tests for enabling ASPX pages to be given dependencies, to avoid ever having to call the <code><span class="code-keyword">new</span></code> keyword directly. This may be taken further to wire up dependencies within a presenters-layer or <a href="http://www.martinfowler.com/eaaCatalog/serviceLayer.html">service layer</a>, as well. </p>

<h4>Design by Contract</h4>

<p>Design-by-Contract (DBC) is quite simply the best way to never have to use the debugger again. Although infrequently discussed, this technique should be given the same amount of praise that test-driven development receives. (Not that I'm saying that DBC gets jealous, but it should.) It increases quality, reduces checks for null, reduces debugging time, and greatly improves the overall stability of an application. To be more technically descriptive, DBC is a technique for contractually obligating users of your code (which is usually you, yourself) to use methods and properties in a particular way and for those methods and properties to promise to successfully carry out the given request. If the contract is not followed, an exception is thrown. It may seem a bit drastic at first, but it goes a long way to improving code quality. With DBC, "pre-conditions" assert what contractual obligations must be adhered to when invoking a method or property. "Post-conditions" assert what contractual obligations have been ensured. I highly recommend reading an <a href="http://devlicio.us/blogs/billy_mccafferty/archive/2006/09/22/Design_2D00_by_2D00_Contract_3A00_-A-Practical-Introduction.aspx">introduction to Design-by-Contract</a>; you'll be hooked on using it very quickly. The sample projects included with this article use a modified <a href="http://www.codeproject.com/csharp/designbycontract.asp">DBC class originally written by Kevin McFarlane</a>. The original allows conditional compilation for turning contracts on for debug mode and off for release mode while the variation included in this article's samples maintains contractual obligations regardless of compilation mode. In my opinion, a contract is always a contract and the behavior should never vary.</p>

<p>In the code, you'll find that pre-conditions are declared with <code>Check.Require</code> while post-condition are declared with <code>Check.Ensure</code>. As DBC is not domain-specific, this class is appropriately pulled out into a reusable, utilities library in the "enterprise" sample.</p>
<a name="BASIC_APP"></a>
<h3>The Basic Sample Application</h3>

<p>So what are we working with here? The basic application fulfills the following user stories: </p>

<ul>
<li>User may view listing of suppliers and their products. </li>

<li>User may view listing of existing customers. </li>

<li>User may view details of customer. </li>

<li>User may view a listing of past orders placed by a customer. </li>

<li>User may view a listing of order summaries, including product name and total quantity, placed by a customer. </li>

<li>User may edit customer details. </li>

<li>User may add a new customer. </li>
</ul>

<p>Regardless of how valuable this application may or may not be, the above user stories are enough to demonstrate the primary aspects of NHibernate integration. To assist with keeping logical tiers loosely coupled, the included sample application is split into four projects: Tests, Web, Core and Data. As a policy, I use &lt;ProjectName&gt;.&lt;LayerName&gt; for naming projects; e.g., <em>BasicSample.Data</em>. Although this simple separation of concerns will work for now, a more realistic architecture will be discussed later. In peeling the layers of the onion, let's begin with the testing layer and work our way towards the simple presentation layer. </p>
<a name="TESTS"></a>
<h3>BasicSample.Tests with NUnit, NUnitAsp, Rhino Mocks and Fit</h3>

<p>I'll assume you can probably guess what this project is for. In the first edition of this article, unit testing was only lightly discussed. As industry, and personal, experience has proven, test-driven development is a pivotal factor in producing high quality products which are more adaptable to change. Furthermore, taking a test-driven approach tends to produce better designs and, as a side effect, creates a lot of perfectly valid technical documentation. For a terrific beginner's introduction to a "day in the life" of test-driven development, take a look at Kent Beck's <a href="http://www.amazon.com/Test-Driven-Development-Addison-Wesley-Signature/dp/0321146530/ref=pd_bbs_sr_1/104-5590703-8892739?ie=UTF8&amp;s=books&amp;qid=1174968315&amp;sr=8-1">Test-Driven Development: By Example</a>. Examining the unit tests of the sample application provides an overview of how the application is structured and what functionality is available. After taking a look at the unit tests, we'll delve further into the code they test. </p>

<h4>A Note on Unit Test Performance</h4>

<p>It's imperative for unit tests to be blazing fast. If a suite of unit tests takes too long to run, developers stop running them - and we want them running unit tests all the time! In fact, if a test takes more than 0.1 second to run, the test is probably too slow. Now, if you've done unit testing in the past, you know that any unit test requiring access to a live database takes much longer than this to run. With <a href="http://www.nunit.org/">NUnit</a>, you can put tests into categories, making it easy to run different groups of tests at a time, thus excluding the tests that connect to a database most of the time. But at the very least, these "slow" tests should be run every night within a <a href="http://www.martinfowler.com/articles/continuousIntegration.html">Continuous Integration</a> environment. Here's a quick example of categorizing an NUnit, unit test:</p>

<div class="SmallText" id="premain0" style="width: 100%; cursor: pointer;"><img preid="0" src="minus.gif" id="preimg0" height="9" width="9"><span preid="0" style="margin-bottom: 0pt;" id="precollapse0"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre0" lang="cs">[TestFixture]
[Category(<span class="code-string">"</span><span class="code-string">Database Tests"</span>)]
<span class="code-keyword">public</span> <span class="code-keyword">class</span> SomeTests
{
    [Test]
    <span class="code-keyword">public</span> <span class="code-keyword">void</span> TestSomethingThatDependsOnDb() { ... }
}</pre>

<h4>Domain Layer Unit Tests</h4>

<p>For simplicity, the domain layer of this application is light, to say the least. But even in the lightest of domain layers, it's important to have, at a minimum, every non-exception path covered by a unit test. The domain layer tests may be found in the namespace <code>BasicSample.Tests.Domain</code>. (As a side, is it overkill that <code>CustomerTests.CanCreateCustomer</code> tests the getter/setter of almost every property? It's startling how many trivial bugs you catch in the process.) While reviewing the tests, you may notice the class <em>DomainObjectIdSetter.cs</em>; the motivations for this class will be discussed later.</p>

<p>To run the unit tests, open NUnit, go to File/Open Project and open <em>BasicSample.Tests/bin/Debug/BasicSample.Tests.dll</em>. To prevent the more time-consuming tests from running, go to the Categories tab within NUnit and double-click both "Database Tests" and "Web Smoke Tests." Additionally, click "Exclude these categories" at the bottom. Now, when you run the unit tests, only the domain logic tests will run and not be slowed down by HTTP and database access tests. For such a small application, the added overhead of the "slow" tests is almost negligible, but can add many minutes to running the unit tests of larger apps. </p>

<h4>Using Test Doubles for the Data Access Layer</h4>

<p>Before getting into simulating the database layer, it should be noted that a nomenclature exists for describing different types of simulated services. Dummies, fakes, stubs and mocks are all used to describe different types of simulated behavior. An <a href="http://www.martinfowler.com/articles/mocksArentStubs.html">overview of the differences</a> highlights a few which will be included in Gerard Meszaros' upcoming <a href="http://xunitpatterns.com/">XUnit Test Patterns</a>. Meszaros offers "test double" to generically describe any of these behaviors. Stubs and mocks are two such test doubles demonstrated in the sample code. </p>

<p>Unless you're specifically testing DAO classes, you usually don't want to run unit tests that are dependent on a live database. They're slow and volatile by nature; i.e., if the data changes, the tests break. And when testing domain logic, unit tests shouldn't break if the database changes. But the major obstacle is that domain objects themselves may depend on DAOs. Using the abstract factory pattern that is in place in the sample (discussed later), and the associated DAO interfaces, we can inject DAO test doubles into the domain objects, thereby simulating communications with the database. An example is included in the test <code>CustomerTests.CanGetOrdersOrderedOnDateUsingStubbedDao</code>. The following snippet, from the unit test, creates the DAO stub and injects it into <code>customer</code> via a public setter. Since the setter only expects an implementation of the <code>IOrderDao</code> interface, the stub DAO easily replaces all of the live-database behavior.</p>

<div class="SmallText" id="premain1" style="width: 100%; cursor: pointer;"><img preid="1" src="minus.gif" id="preimg1" height="9" width="9"><span preid="1" style="margin-bottom: 0pt;" id="precollapse1"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre1" lang="cs">Customer customer = <span class="code-keyword">new</span> Customer(<span class="code-string">"</span><span class="code-string">Acme Anvils"</span>);
customer.ID = <span class="code-string">"</span><span class="code-string">ACME"</span>;
customer.OrderDao = <span class="code-keyword">new</span> OrderDaoStub();</pre>

<p>As an alternative to writing DAO stubs, which are generally static by nature and often amount to quite a bit of "not implemented" code, it is also possible to mock the DAO using a tool such as <a href="http://ayende.com/projects/rhino-mocks.aspx">Rhino Mocks</a> or <a href="http://nmock.org/">NMock</a>. Either selection works perfectly well, but Rhino Mocks invokes methods in a strongly typed manner as opposed to using strings, as NMock does. This makes its usage compile-time checked and assists with renaming properties and methods. The test <code>CustomerTests.CanGetOrdersOrderedOnDateUsingMockedDao</code> demonstrates using Rhino Mocks 3.0 to create a mocked <code>IOrderDao</code>. Although setting up a mocked object appears more complicated than setting up a stub, the added flexibility and greatly reduced "not implemented" code are convincing benefits. The following code, found in the class <em>MockOrderDaoFactory.cs</em>, shows how <code>IOrderDao</code> is mocked with Rhino Mocks. It essentially creates a "static" mock, or stub, in the fact that it doesn't matter what is passed in for arguments; it'll always return the same example orders created by <code>TestOrdersFactory</code>. But mocking with Rhino Mocks isn't limited to dumb reflexes, such as this, and can be as variably responsive as required. </p>

<div class="SmallText" id="premain2" style="width: 100%; cursor: pointer;"><img preid="2" src="minus.gif" id="preimg2" height="9" width="9"><span preid="2" style="margin-bottom: 0pt;" id="precollapse2"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre2" lang="cs"><span class="code-keyword">public</span> IOrderDao CreateMockOrderDao() {
    MockRepository mocks = <span class="code-keyword">new</span> MockRepository();

    IOrderDao mockedOrderDao = mocks.CreateMock&lt;IOrderDao&gt;();
    Expect.Call(mockedOrderDao.GetByExample(<span class="code-keyword">null</span>)).IgnoreArguments()
        .Return(<span class="code-keyword">new</span> TestOrdersFactory().CreateOrders());
    
    mocks.Replay(mockedOrderDao);

    <span class="code-keyword">return</span> mockedOrderDao;
}</pre>

<p>Unfortunately, more often than not, you're maintaining legacy code that has no semblance of the ideal "code-to-interface" that allows for such test-double injection. Usually, there are many explicit dependencies to concrete objects, and it is difficult to replace data-access objects with test doubles to simulate a live database. In these situations, your options are to either refactor the legacy code to fit within a test harness, or to use an object mocking tool such as <a href="http://www.typemock.com/">TypeMock</a>. With TypeMock, it is even possible to mock sealed and singleton classes - an impressive feat to pull off without such a tool. Albeit powerful, TypeMock is best left alone unless absolutely needed; using TypeMock prematurely makes it tempting to not code to interface. The more appropriate course to take when working with legacy code - time and budget permitting - is to refactor the code for greater flexibility. <a href="http://www.amazon.com/gp/product/0131177052/102-1170069-1054529?v=glance&amp;n=283155" target="_top">Working Effectively with Legacy Code</a> by Michael Feathers is full of great ideas for refactoring legacy code into a test harness.</p>

<h4>Unit Testing NHibernate DAOs</h4>

<p>In the previous edition of this article, NHibernate's <code>ISession</code> was stored and retrieved solely via <code>System.Runtime.Remoting.Messaging.CallContext</code>. Although perfectly fine for WinForms and NUnit tests, this is a very bad idea for ASP.NET as the <code>ISession</code> may be "lost" under load. (These <a href="http://forum.springframework.net/showthread.php?t=572">two</a> <a href="http://piers7.blogspot.com/2005/11/threadstatic-callcontext-and_02.html">articles</a> provide further explanation for why using <code>CallContext</code> in ASP.NET applications is a bad idea.) For proper integration with ASP.NET applications, the <code>ISession</code> should be stored in <code>HttpContext.Current.Items</code>; but doing so forces you to simulate an HTTP context when running unit tests. It also prevents the framework from easily porting to WinForms. A better approach is to use the proper repository when appropriate. So if a web context is available, then use <code>HttpContext</code>; otherwise, use <code>CallContext</code>. Implementation details of this combined approach are discussed later. (A thanks goes out to the many people in the article comments that raised this concern.) Take a look at <em>BasicSample.Tests/Data/CustomerDaoTests.cs</em> for unit tests that are HTTP-agnostic with respect to how the <code>ISession</code> is managed. As a side, as you'll see in the unit test, unless you want data changes made within your tests to be committed to the database, it's a good idea to rollback the transaction. </p>

<p>As demonstrated in the sample, it's possible to create a generic DAO that works for any persistent object. (Details of which will be discussed later.) This leads to the discussion of what should be tested and how should it be done? Should each concrete DAO be fully tested? How is the test data maintained? Personal experience suggests these guidelines: </p>

<ul>
<li>Make sure a unit test exists to test each method of the generic DAO, once. For example, if you have 10 DAOs which implement the generic DAO, only one of them needs to be fully tested for each method. Unit testing the other nine implementations of the generic DAO will provide little added value. </li>

<li>Make sure a unit test exists to test each extension method to the generic DAO. For example, if you have a <code>CustomerDao</code> class which inherits from the generic DAO and then extend it with an additional method, such as <code>GetActiveCustomers()</code>, then a unit test should be written to test this extension method. </li>

<li>Make sure a unit test exists to fully test each "specialty" DAO. For instance, the DAO <em>BasicSample.Data/HistoricalOrderSummaryDao.cs</em> does <em>not</em> inherit from the generic DAO and would be considered a specialty DAO. Therefore, a unit test exists to test each of its methods. </li>

<li>Use a tool such as <a href="http://www.ndbunit.org/">NDbUnit</a> to put the test database into a known state both before and after DAO unit tests are run. </li>

<li>Always remember, unit tests should never depend on the actions of another unit test! They should be independent and able to be run in isolation. E.g., a delete-test should not depend on the previous insert-test having successfully completed. Note that <code>TestFixtureSetUp</code>, and other setup/teardown methods, are OK to run while still being able to consider the test to have run in isolation. </li>
</ul>

<h4>Using Fit Test Doubles for the Presentation Layer</h4>

<p>When the domain layer was tested, test doubles were used to simulate NHibernate communications with the database. Similarly, it's handy at times to use this same approach when testing the presentation layer. Suppose you're working on an ASP.NET project with a dedicated "creative" team. The creative folks, with their black turtlenecks, are in charge of developing the look and feel of the application. While they're working on the graphical layout, you shouldn't be hindered to develop a presentation layer for viewing domain-logic &amp; data-access results and for getting client feedback, while still being able to put off decisions such as master-page setup, security enforcement, and other presentation-specific decisions. In another scenario, suppose you're working on a number of complicated business rules which you'd like the client to be able to verify without having to write a few dozen unit tests to encapsulate each minor variation. <a href="http://fit.c2.com/">FIT (Framework for Integrated Test)</a> is a tool for developers to fake the presentation layer very quickly and provide for a more collaborative effort between developers and project stakeholders. As the Fit site states, this is done "to learn what the software <em>should</em> do and what it <em>does</em> do. It automatically compares customers' expectations to actual results." Arguably, a tool such as this isn't "basic" and isn't required for testing NHibernate; but the importance of test-driven development needs to be emphasized and a tool such as Fit, when used appropriately, is just as applicable to software quality as NUnit. </p>

<p>For viewing Fit test results, you can use <a href="http://msdn.microsoft.com/msdnmag/issues/05/02/ExcelUnitTests/default.aspx">WinFITRunnerLite</a>, which runs Fit tests in a Windows client similar to NUnit, or <a href="http://fitnesse.org/">FitNesse</a>, which provides a web-based wiki for modifying test inputs and viewing Fit test results. Although it takes a little more setup, FitNesse provides a very flexible framework for allowing clients to participate in validating coding logic and application workflow. The following screenshot shows a simple example of the output you'd expect to see from running a calculator test with FitNesse: </p>
<img alt="Screenshot - FitNesse.jpg" src="fitnesse.jpg" height="376" width="640"> 
<p>Although implementation examples of Fit tests are beyond the scope of this article, my hope is that you'll get interested in learning more about this powerful framework. In addition to the websites listed previously, extensive information concerning the use of Fit and FitLibrary, an extension to Fit, may be found in <a href="http://www.amazon.com/Fit-Developing-Software-Framework-Integrated/dp/0321269349/ref=pd_bbs_sr_1/104-5590703-8892739?ie=UTF8&amp;s=books&amp;qid=1175115242&amp;sr=8-1">Fit for Developing Software</a> by Rick Mugridge and Ward Cunningham. </p>

<h4>Running ASPX "Smoke Tests" with NUnitAsp</h4>

<p>At this point, we've unit tested the domain layer and the data-access layer and learned about testing with a rough presentation layer, using Fit, for getting clients more involved. It's now time to test the ASPX pages themselves. <a href="http://nunitasp.sourceforge.net/">NUnitAsp</a> is a class library for performing these types of unit tests. Although you can get rather sophisticated using NUnitAsp with your WebForms testing, I find that NUnitAsp is best for running "smoke tests" from the continuous integration server to verify that no page is blatantly breaking. Taking NUnitAsp further than this tends to result in a lot of maintenance of the associated unit testing code. Since these HTTP unit tests are slow by nature, they're rarely run and, consequently, lightly maintained; therefore, they should be kept as simple as possible. <em>BasicSample.Tests/Web/WebSmokeTests.cs</em> demonstrates a sampling of these unit tests. Although trivially simple, these smoke tests go a long way towards verifying that your presentation layer is responsive, that database communications are working correctly, and that NHibernate HBMs are, for the most part, error-free. As an added bonus, if the smoke tests are directed at the production environment immediately after a deployment, they serve to pre-load all the ASPX pages for a more responsive experience for the very next visitor. You should include a smoke test for every URL-accessible web page in your application. To help organize them, create a separate test class for each grouping of smoke tests. For example, all the smoke tests for an admin section of the website would be found in a file called <em>AdminSmokeTests.cs</em>. </p>
<a name="CORE"></a>
<h3>BasicSample.Core for Defining the Domain Layer</h3>

<p>The <em>BasicSample.Core</em> project contains the domain model and NHibernate HBM files. This project also contains interfaces, describing the data access objects, in the <code>BasicSample.Core.DataInterfaces</code> namespace. (Arguably, the HBM files logically belong in the <em>BasicSample.Data</em> assembly, but the maintenance convenience of having the HBM files physically close to the domain objects they describe far outweighs this break in encapsulation.) </p>

<h4>Separated Interface, Implemented</h4>

<p>You'll notice that the <em>BasicSample.Core</em> project does not contain implementation details of data access objects, only <em>interfaces</em> describing the services it needs. The concrete DAO classes, which implement these interfaces, are found within <em>BasicSample.Data</em>. As described previously, this technique is called <a href="http://www.martinfowler.com/eaaCatalog/separatedInterface.html">Separated Interface</a>. If you consider <em>BasicSample.Core</em> to be an "upper-level layer" and <em>BasicSample.Data</em> to be a "lower-level layer", then, as Robert Martin describes, "each of the upper-level layers declares an abstract interface for the services that it needs. The lower-level layers are then realized from these abstract interfaces. ... Thus, the upper layers do not depend on the lower layers. Instead, the lower layers depend on abstract service interfaces <em>declared</em> in the upper layers". </p>

<p>To see this in action, the data interfaces are described in the namespace <code>BasicSample.Core.DataInterfaces</code>. <code>IDao</code> is a generic interface for providing typical data access functionality. <code>IDaoFactory</code> then acts as an interface for one or more DAO factory classes. Coding to the <code>IDaoFactory</code> interface allows you to create one concrete DAO factory for production code, and another concrete DAO factory for returning DAO test doubles for unit testing purposes. (This is an example of using the <a href="http://www.dofactory.com/Patterns/PatternAbstract.aspx">abstract factory pattern</a>.) And as previously examined in <em>BasicSample.Tests</em>, leveraging <a href="http://www.connextra.com/aboutUs/mockobjects.pdf">mock objects in unit tests</a> provides a means for testing a single responsibility at a time.</p>

<h4>Collection Generics Examined</h4>

<p>By far, one of the greatest benefits that C# 2.0 has brought to the table is the inclusion of generics. With generics, more code reuse can be effectively realized while still enforcing strongly typed coding "contracts". In the previous edition of this article, <a href="http://www.ayende.com/projects/nhibernate-query-analyzer/generics.aspx">Ayende's very useful, but deprecated, NHibernate.Generics</a> was used to integrate NHibernate with .NET generics. But now that NHibernate 1.2 natively supports generics, this class library is no longer necessary. If you've used Ayende's library in the past, you've got a bit of work ahead of you to completely migrate away from it, especially if you used the automatic wiring for managing parent/child relationships. But don't let this stop you as you can still upgrade to NHibernate 1.2 without having to immediately refactor out the automatic wiring...but you'll still want to do so sooner rather than later. More information about the steps required to refactor away from Ayende's NHibernate.Generics is found below in <a href="#MIGRATING">Migrating from NHibernate 1.0x to 1.2</a>. A drawback to Ayende's NHibernate.Generics was that internal collections needed to be exposed with both getters and setters. This broke encapsulation and allowed collections to be manipulated or modified in unintended ways - think of it as collection harassment. Now that NHibernate supports generics natively, better collection encapsulation techniques may be employed. The following code from <em>Customer.cs</em> and <em>Customer.hbm.xml</em> shows a better encapsulation of generic collections. </p>

<div class="SmallText" id="premain3" style="width: 100%; cursor: pointer;"><img preid="3" src="minus.gif" id="preimg3" height="9" width="9"><span preid="3" style="margin-bottom: 0pt;" id="precollapse3"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre3" lang="cs"><span class="code-keyword">public</span> IList&lt;Order&gt; Orders {
    <span class="code-keyword">get</span> { <span class="code-keyword">return</span> <span class="code-keyword">new</span> List&lt;Order&gt;(orders).AsReadOnly(); }
    <span class="code-keyword">protected</span> <span class="code-keyword">set</span> { orders = value; }
}

<span class="code-keyword">public</span> <span class="code-keyword">void</span> AddOrder(Order order) {
    <span class="code-keyword">if</span> (order != <span class="code-keyword">null</span> &amp;&amp; !orders.Contains(order)) {
        orders.Add(order);
    }
}

<span class="code-keyword">public</span> <span class="code-keyword">void</span> RemoveOrder(Order order) {
    <span class="code-keyword">if</span> (orders.Contains(order)) {
        orders.Remove(order);
    }
}

<span class="code-keyword">private</span> IList&lt;Order&gt; orders = <span class="code-keyword">new</span> List&lt;Order&gt;();</pre>
<br>
<div class="SmallText" id="premain4" style="width: 100%; cursor: pointer;"><img preid="4" src="minus.gif" id="preimg4" height="9" width="9"><span preid="4" style="margin-bottom: 0pt;" id="precollapse4"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre4" lang="xml"><span class="code-keyword">&lt;</span><span class="code-leadattribute">bag</span> <span class="code-attribute">name</span><span class="code-keyword">="</span><span class="code-keyword">orders"</span> <span class="code-attribute">table</span><span class="code-keyword">="</span><span class="code-keyword">Orders"</span> <span class="code-attribute">inverse</span><span class="code-keyword">="</span><span class="code-keyword">true"</span> <span class="code-attribute">cascade</span><span class="code-keyword">="</span><span class="code-keyword">all"</span><span class="code-keyword">&gt;</span>
    <span class="code-keyword">&lt;</span><span class="code-leadattribute">key</span> <span class="code-attribute">column</span><span class="code-keyword">="</span><span class="code-keyword">CustomerID"</span> <span class="code-keyword">/</span><span class="code-keyword">&gt;</span>
    <span class="code-keyword">&lt;</span><span class="code-leadattribute">one-to-many</span> <span class="code-attribute">class</span><span class="code-keyword">="</span><span class="code-keyword">BasicSample.Core.Domain.Order, BasicSample.Core"</span> <span class="code-keyword">/</span><span class="code-keyword">&gt;</span>
<span class="code-keyword">&lt;</span><span class="code-keyword">/</span><span class="code-leadattribute">bag</span><span class="code-keyword">&gt;</span></pre>

<p>Setting the orders collection setter to <code><span class="code-keyword">protected</span></code> allows NHibernate to populate the collection without having to depend on a private member directly and without having to expose the setter publicly. Alternatively, the NHibernate setting <code>access=<span class="code-string">"</span><span class="code-string">field"</span></code> could be used to set a private member directly, but the use of this should be carefully considered and only used when warranted. In the sample code above, note what <code>AddOrder</code> and <code>RemoveOrder</code> have done to the <code>Customer</code> class. They've shamelessly polluted the class by adding collection management concerns to the containing class. Imagine the headache this would turn into if <code>Customer</code> ended up having a number of collections along with methods for managing each one. In instances like this, it's usually best to employ a custom collection.</p>

<p>As a simple example of using a custom collection, the <code>Supplier</code> class may have a number of <code>Product</code> items associated with it. The caveat is that NHibernate needs to map to an <code>IList</code> collection; consequently, two collections are maintained. The first is the products collection itself, which NHibernate is aware of, and the second is a products collection wrapper which exposes the custom collection. The following code from <em>Supplier.cs</em> and <em>Products.cs</em> demonstrates this.</p>

<div class="SmallText" id="premain5" style="width: 100%; cursor: pointer;"><img preid="5" src="minus.gif" id="preimg5" height="9" width="9"><span preid="5" style="margin-bottom: 0pt;" id="precollapse5"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre5" lang="cs"><span class="code-comment">//</span><span class="code-comment"> Within Supplier.cs...</span>

<span class="code-keyword">public</span> Products Products {
    <span class="code-keyword">get</span> {
        <span class="code-keyword">if</span> (productsWrapper == <span class="code-keyword">null</span>) {
            productsWrapper = <span class="code-keyword">new</span> Products(products);
        }

        <span class="code-keyword">return</span> productsWrapper;
    }
}

<span class="code-keyword">private</span> Products productsWrapper;
<span class="code-comment">//</span><span class="code-comment"> NHibernate binds directly to this member by the access="field" setting</span>
<span class="code-keyword">private</span> IList<product> products = <span class="code-keyword">new</span> List&lt;Product&gt;();


<span class="code-comment">//</span><span class="code-comment"> Within Products.cs</span>

<span class="code-keyword">public</span> Products(IList<product> products) {
    <span class="code-keyword">this</span>.products = products;
}

<span class="code-keyword">public</span> <span class="code-keyword">void</span> Add(Product product) {
    <span class="code-keyword">if</span> (product != <span class="code-keyword">null</span> &amp;&amp; !products.Contains(product)) {
        products.Add(product);
    }
}

<span class="code-keyword">private</span> IList<product> products;</product></product></product></pre>

<p>Although simplistic, the example code should cover most of your custom collection needs. But in some cases, a full-blown generic, custom collection is required. One of the most common scenarios includes creating a custom collection which implements <code>BindingList</code>. In these types of situations, it's necessary to leverage NHibernate's <code>IUserCollectionType</code>. A good example of implementing this may be <a href="http://analog-man.blogspot.com/2007/01/bridge-gap-between-your-nhibernate.html">found here</a>.</p>

<h4>Generic IDs and Object Comparisons</h4>

<p>In <em>BasicSample.Core</em>, each persistable domain object inherits from <code>DomainObject</code>. This class handles most of the work involved with comparing two domain objects for equality. (A detailed discussion of this object may be found in a <a href="http://devlicio.us/blogs/billy_mccafferty/archive/2007/04/25/using-equals-gethashcode-effectively.aspx">devlicio.us blog post</a>.) <code>DomainObject</code> is also a generic class which accepts a data type declaring the ID type of the domain object. This generic property provides the ability to have one domain object which uses a <code><span class="code-SDKkeyword">string</span></code> as an ID, such as <code>Customer</code>, and another to have a <code><span class="code-keyword">long</span></code> as an ID, such as <code>Order</code>. It should be duly noted that in the previous edition of this article, the ID property had both a public getter and setter. Although the getter is essential, the public setter opened Pandora's box for corrupting existing data. Assume you retrieved a customer from the database and accidentally set its ID to another customer's ID. When the customer gets saved back to the database, its data overwrites that of the other customer. For a more subtle example, assume the <code>Customer</code> class is being used as a pseudo DTO being returned from an edit screen. With a public ID setter, the developer sets the ID and the applicable properties and returns it to another object which takes care of transferring the DTO information to the "real" customer pulled from the database. Mind you, both the DTO and the "real" customer are being passed around as instances of <code>Customer</code>. So if, during maintenance, a developer doesn't realize that the <code>Customer</code> being returned from the view should be treated as a DTO and not as a "real" customer, and proceeds to invoke save on it directly, then it's quite probable that a lot of live customer data has been lost since it was overwritten with the sparse DTO data. The primary weakness behind this is the fact that ID had a public setter. Therefore, it is best that a domain object's ID only be set by NHibernate when loading an object from the database and is hidden from public setting. But there are situations wherein a domain object has an assigned ID. (Personally, I find no place for assigned IDs and avoid them whenever possible, but understand that an argument can be made for their use. You can find a further rant in <em>BasicSample.Web/AddCustomer.aspx</em>.) For situations when an assigned ID is required, an interface is included called <code>IHasAssignedId</code>. This interface defines a method for setting the ID. So although it provides a doorway for setting the ID, it requires a bit more thought concerning its use and provides a good spot for including ID-assignment business logic. The following snippet exemplifies this within the <code>Customer</code> class. </p>

<div class="SmallText" id="premain6" style="width: 100%; cursor: pointer;"><img preid="6" src="minus.gif" id="preimg6" height="9" width="9"><span preid="6" style="margin-bottom: 0pt;" id="precollapse6"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre6" lang="cs"><span class="code-keyword">public</span> <span class="code-keyword">class</span> Customer : DomainObject&lt;string&gt;, IHasAssignedId&lt;string&gt;
{
    <span class="code-keyword">public</span> <span class="code-keyword">void</span> SetAssignedIdTo(<span class="code-keyword">string</span> assignedId) {
        Check.Require(!string.IsNullOrEmpty(assignedId), 
            <span class="code-string">"</span><span class="code-string">assignedId may not be null or empty"</span>);
        <span class="code-comment">//</span><span class="code-comment"> As an alternative to Check.Require, </span>
            the Validation Application Block could be used <span class="code-keyword">for</span> the following
        Check.Require(assignedId.Trim().Length == <span class="code-digit">5</span>, 
            <span class="code-string">"</span><span class="code-string">assignedId must be exactly 5 characters"</span>);

        ID = assignedId.Trim().ToUpper();
    }
    ...
}</pre>

<p>An obvious drawback to <em>not</em> exposing a public ID setter is that this property becomes essentially unusable to the unit testing framework, unless NHibernate is used to load the object. To skirt this problem, the class <em>BasicSample.Tests/Domain/DomainObjectIdSetter.cs</em> enables you to set the ID of domain objects, even if they do not implement <code>IHasAssignedId</code>. This ability opens many testing possibilities without having to provide a public setter to the ID property. On the flipside, using reflection to set private members, for the benefit of unit tests, should be seen as a non-standard practice and used only when absolutely necessary. It adds complexity and is fragile since it is string based. But for setting the ID property of domain objects, it's a perfect fit for the unit testing layer. </p>

<h4>Mapping the Domain to the Database</h4>

<p>NHibernate provides two means of mapping domain objects to the database: HBMs using XML and mapping attributes. The primary advantage of HBM-XML files is that they are physically separated from the domain objects they describe. This enables the domain objects to remain as POCOs (plain old C# objects), relatively oblivious to how they are associated with the database. But keeping the mapping information separated from the domain objects may also be seen as the primary <em>dis</em>advantage of HBMs in that it requires additional maintenance effort to keep switching between HBMs and the classes they map. (Some people also loathe using XML.) Mapping attributes, on the other hand, are intimately connected to the domain objects and are generally less verbose than their HBM equivalents. Using mapping attributes makes the domain objects more akin to <a href="http://www.martinfowler.com/eaaCatalog/activeRecord.html">Active Records</a> than POCOs. (For true Active Record support, consider using <a href="http://www.castleproject.org/activerecord/index.html">Castle Project's ActiveRecord</a>.) Besides "dirtying" up the domain objects, mapping attributes require a reference to <em>NHibernate.Mapping.Attributes</em> which makes the domain layer a bit less data-access-provider agnostic. On the other hand, do you often find yourself switching out data-access layers completely, anyway? But as a general rule, the domain layer should remain as data-access-provider agnostic as is practical for the design goals of the application. When it comes right down to it, it's a matter of personal preference when deciding between HBMs or mapping attributes. Regardless, when starting a new project, it should be decided which technique will be used; mixing the techniques may lead to confusion as it may not be clear which objects are mapped and which are not. The sample application demonstrates using HBMs for the mapping solution. The following snippet - not found in the sample application - shows an example of using mapping attributes instead of HBMs. Additional <a href="http://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/mapping-attributes.html">information concerning mapping attributes</a> may be found in the NHibernate docs. </p>

<div class="SmallText" id="premain7" style="width: 100%; cursor: pointer;"><img preid="7" src="minus.gif" id="preimg7" height="9" width="9"><span preid="7" style="margin-bottom: 0pt;" id="precollapse7"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre7" lang="cs">[NHibernate.Mapping.Attributes.Class]
<span class="code-keyword">public</span> <span class="code-keyword">class</span> Customer
{
    [NHibernate.Mapping.Attributes.Property]
    <span class="code-keyword">public</span> <span class="code-keyword">string</span> FirstName { ... }
    ...
}</pre>

<h4>NHibernate Support for Nullables</h4>

<p>A new capability that NHibernate 1.2 brings to the table is support for nullable types. Previously, a reference to <em>Nullables.NHibernate</em> supported nullable types, but it is no longer needed. There's no need to treat nullable property mappings, within the HBMs, any differently than other property mappings; simply map the nullable property as you would any other. NHibernate is smart enough to transfer <code>null</code> between the database and the nullable property it maps to. Take a look at <em>BasicSample.Core/Domain/Order.cs</em> for an example of using a nullable <code>DateTime</code>. Although support for nullables is now trivially simple to implement, it should only be used after careful consideration. My own experiences have led me to hardly ever create columns in the database which allow null. In my opinion, mapping null to primitive types has little meaning within the database nor within the domain layer. Nullable <code>DateTime</code> properties are about the only exception that come to mind. Obviously, there are plenty of valid situations for using <code>null</code> with non-primitive relationships; but even then, use of the <a href="http://www.cs.oberlin.edu/%7Ejwalker/nullObjPattern/">Null Object pattern</a> is a great alternative to checks for <code>null</code> scattered about the code. </p>

<h4>NHibernate Support for Stored Procedures</h4>

<p>NHibernate 1.2's support for stored procedures is a critical addition to this framework's capabilities. But what's so great about integrating with stored procs if all the CRUD is already taken care of by NHibernate? Two reasons: working with legacy databases and performing reporting queries. Creating a stored procedure to return query-intensive reporting data is the optimal way for polling the database. To illustrate, the Northwind database maintains orders placed by each customer. Assume you need to return the quantity of each product ever ordered by a specific customer. The class <em>BasicSample.Core/Domain/HistoricalOrderSummary.cs</em> is a <a href="http://c2.com/cgi/wiki?ValueObject">value object</a> which encapsulates this summary information. Note that this class does not inherit from <code>DomainObject</code> and does not have a corresponding HBM file. This is considered an "unmanaged" class from NHibernate's perspective, not to be confused with <a href="http://www.codeproject.com/csharp/unmanage.asp">unmanaged C#</a>. The file <em>HistoricalOrderSummary.hbm.xml</em> declares a named query which makes a call to the stored procedure <code>CustOrderHist</code> for returning the needed reporting data. (Details of how this data is converted into domain objects will be discussed next, while dissecting the <em>BasicSample.Data</em> project.) </p>

<p>Providing capabilities for interacting with stored procedures brings up the issue of deciding what should be performed by stored procedures and what should be performed by the domain layer. As an alternative to the stored proc, to meet the previously stated requirements, the C# code could have retrieved all the orders placed by the given customer, looped through all of them and summed the quantity of each product. But it was clear that having SQL Server perform this summing was far more efficient; imagine if the customer had placed thousands of orders. If, on the other hand, performance analysis had shown little difference in efficiency between letting the domain layer do the work vs. a stored procedure, then go with the domain layer to do the work. You'll find that this will lend itself to a more complete domain-driven design and better reusability of the resulting code. As is frequently encountered during development, this is a balance between better domain-driven design and optimized performance ... always lean towards the domain until a bottleneck is discovered. (As mentioned in the introduction, see <a href="http://www.codeproject.com/useritems/NHibernate_Perf.asp">Peter Weissbrod's article</a> for an introduction to identifying NHibernate related bottlenecks.) Incidentally, the first NHibernate project I was involved with, which was about 50,000 LOC, required about six stored procedures in all to help optimize the data-querying capabilities. This should serve to illustrate how much you can put into the domain layer without taking an appreciable hit to performance. </p>
<a name="DATA"></a>
<h3>BasicSample.Data for Implementing NHibernate Communications</h3>

<p>The <em>BasicSample.Data</em> project contains the concrete DAOs and implementation details for communicating with the database and managing NHibernate sessions. </p>

<h4>The DAO Factory and Generic DAO</h4>

<p>The DAO factory and generic DAO objects have been implemented as <code>NHibernateDaoFactory</code> and <code>AbstractNHibernateDao</code>, respectively. With a few key modifications, these are C# ports of the Java versions <a href="http://www.hibernate.org/328.html">described in detail at Hibernate's website</a>. I highly recommend reviewing this article in detail. (Note that a bug has been fixed from the previous edition of this article wherein calling <code>CommitChanges()</code>, when a transaction was not being used, was not flushing the session; see <code>AbstractNHibernateDao.CommitChanges</code> for the fixed code. Additionally, due to NHibernate 1.2's native support of generics, DAO list results may now be retured directly without first going through a convert-to-generic-list process.) The most impressive thing to note, by using a generic DAO, is that it takes just a few lines of code to create a full-blown DAO ready for use: </p>

<ol>
<li>Add a new inline interface, and associated retrieval method, to <em>BasicSample.Core/DataInterfaces/IDaoFactory.cs</em>. </li>

<li>Add a new inline implementation for the new DAO, and retrieval method, to <em>BasicSample.Data/NHibernateDaoFactory.cs</em>. </li>
</ol>

<p>Looking at the <code>ICustomerDao</code>/<code>CustomerDao</code> example in the basic sample application, it took about five lines of code to define the interface and implement the concrete DAO ... not too bad. </p>

<p>Occasionally, it's necessary to extend the abstract, generic DAO with specialty methods. The interface <em>BasicSample.Core/DataInterfaces/IOrderDao.cs</em> defines one such example. In this case, the domain layer needs the orders-DAO to return all the orders found within a given date range. For manageability, any DAOs which extend the abstract DAO should be placed in their own file and not declared inline as <code>ICustomerDao</code> was. Likewise, this also applies to the concrete implementation demonstrated with <em>BasicSample.Data/OrderDao.cs</em>. </p>

<h4>Retrieving Reporting Data from Stored Procs</h4>

<p>While examining the <em>BasicSample.Core</em> project, we encountered <em>HistoricalOrderSummary.hbm.xml</em> which declared a named query to communicate with a stored procedure for the purposes of retrieving reporting data. In the <em>BasicSample.Data</em> project we find the concrete DAO, <em>HistoricalOrderSummaryDao.cs</em>. This DAO includes the following code to invoke the named query, receive the results, and pass each returned row into the constructor of the value object, <code>HistoricalOrderSummary</code>. The key is the call to <code>SetResultTransformer</code> which informs NHibernate how to translate the results into a new instance of <code>HistoricalOrderSummary</code>. Review the NHibernate documentation to learn about other available options for this translation procedure. </p>

<div class="SmallText" id="premain8" style="width: 100%; cursor: pointer;"><img preid="8" src="minus.gif" id="preimg8" height="9" width="9"><span preid="8" style="margin-bottom: 0pt;" id="precollapse8"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre8" lang="CS">IQuery query = NHibernateSession.GetNamedQuery(<span class="code-string">"</span><span class="code-string">GetCustomerOrderHistory"</span>)
    .SetString(<span class="code-string">"</span><span class="code-string">CustomerID"</span>, customerId)
    .SetResultTransformer(
    <span class="code-keyword">new</span> NHibernate.Transform.AliasToBeanConstructorResultTransformer(
        <span class="code-keyword">typeof</span> (HistoricalOrderSummary).GetConstructors()[<span class="code-digit">0</span>]));</pre>

<h4>Handling the NHibernate Session</h4>

<p>At the core of integrating with NHibernate is <em>BasicSample.Data/NHibernateSessionManager.cs</em>. This <a href="http://www.yoda.arachsys.com/csharp/singleton.html">thread-safe, lazy singleton</a> performs the following duties:</p>

<ul>
<li><em>Builds the <code>ISession</code> factory when instantiated for the first time.</em> The class is a singleton because building the session factory is very expensive. In the previous edition of this article, an application setting within <em>web.config</em> declared which assembly contained the HBM files. This is not necessary. Instead, the mapping attribute should be included in the <code>hibernate-configuration</code>. For example, <em>web.config</em> includes the following declaration, within the NHibernate configuration settings, letting NHibernate know where to find the HBMs: <code><span class="code-keyword">&lt;</span>mapping assembly=<span class="code-string">"</span><span class="code-string">BasicSample.Core"</span> /<span class="code-keyword">&gt;</span></code>. Besides being a cleaner approach than using an application setting, this lends itself better towards managing multiple databases concurrently. </li>

<li><em>Handles commands sent to the context-specific <code>ISession</code>.</em> Examples include creating/closing the current <code>ISession</code>, registering an <code>IInterceptor</code> (which needs to be done, incidentally, before a transaction is begun), and managing transactions. </li>

<li><em>Stores and retrieves the context-specific <code>ISession</code>.</em> There are various ways to manage the life-cycle of the <code>ISession</code>; one such approach, called "Open Session in View," is presented shortly. <code>NHibernateSessionManager</code> does not dictate <em>when</em> the <code>ISession</code> needs to be created and destroyed, but it does dictate <em>how</em> the <code>ISession</code> is stored. In the previous edition of this article, <code>CallContext</code> was used as the sole means for storage. This is a very bad idea for ASP.NET applications. The corrected approach leverages <code>HttpContext</code> when it is available and <code>CallContext</code> when it is not. Although this forces you to include a reference to <em>System.Web</em>, this enables seamless portability between WebForms and WinForms. Incidentally, NUnit tests work like a WinForms application, and, thus, benefit from this portability. The following code, pulled from <code>NHibernateSessionManager</code>, demonstrates switching between the appropriate context and is worth showing in its entirety: 
<div class="SmallText" id="premain9" style="width: 100%; cursor: pointer;"><img preid="9" src="minus.gif" id="preimg9" height="9" width="9"><span preid="9" style="margin-bottom: 0pt;" id="precollapse9"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre9" lang="cs"><span class="code-keyword">private</span> ITransaction ThreadTransaction {
    <span class="code-keyword">get</span> {
        <span class="code-keyword">if</span> (IsInWebContext()) {
            <span class="code-keyword">return</span> (ITransaction)HttpContext.Current.
                Items[TRANSACTION_KEY];
        }
        <span class="code-keyword">else</span> {
            <span class="code-keyword">return</span> (ITransaction)CallContext.GetData(TRANSACTION_KEY);
        }
    }
    <span class="code-keyword">set</span> {
        <span class="code-keyword">if</span> (IsInWebContext()) {
            HttpContext.Current.Items[TRANSACTION_KEY] = value;
        }
        <span class="code-keyword">else</span> {
            CallContext.SetData(TRANSACTION_KEY, value);
        }
    }
}

<span class="code-keyword">private</span> ISession ThreadSession {
    <span class="code-keyword">get</span> {
        <span class="code-keyword">if</span> (IsInWebContext()) {
            <span class="code-keyword">return</span> (ISession)HttpContext.Current.Items[SESSION_KEY];
        }
        <span class="code-keyword">else</span> {
            <span class="code-keyword">return</span> (ISession)CallContext.GetData(SESSION_KEY); 
        }
    }
    <span class="code-keyword">set</span> {
        <span class="code-keyword">if</span> (IsInWebContext()) {
            HttpContext.Current.Items[SESSION_KEY] = value;
        }
        <span class="code-keyword">else</span> {
            CallContext.SetData(SESSION_KEY, value);
        }
    }
}

<span class="code-keyword">private</span> <span class="code-keyword">bool</span> IsInWebContext() {
    <span class="code-keyword">return</span> HttpContext.Current != <span class="code-keyword">null</span>;
}

<span class="code-keyword">private</span> <span class="code-keyword">const</span> <span class="code-keyword">string</span> TRANSACTION_KEY = <span class="code-string">"</span><span class="code-string">CONTEXT_TRANSACTION"</span>;
<span class="code-keyword">private</span> <span class="code-keyword">const</span> <span class="code-keyword">string</span> SESSION_KEY = <span class="code-string">"</span><span class="code-string">CONTEXT_SESSION"</span>;</pre>
</li>
</ul>

<p>The basic flow for retrieving a session is as follows: </p>

<ol>
<li>The client code calls <code>NHibernateSessionManager.Instance.GetSession()</code>. </li>

<li>If not already instantiated, this singleton object builds the <code>ISession</code> factory, loading HBM mapping files from the appropriate assembly. </li>

<li><code>GetSession</code> looks to see if an <code>ISession</code> is already bound to the appropriate context. </li>

<li>If an open NHibernate <code>ISession</code> is not found, then a new one is opened (bound to an optional <code>IInterceptor</code>) and stored back to the appropriate context. </li>

<li><code>GetSession</code> then returns the context-specific <code>ISession</code>. </li>
</ol>

<p>This flow, as well as the rest of <code>NHibernateSessionManager</code>, follows that closely described in <a href="http://www.amazon.com/gp/product/193239415X/102-1170069-1054529?v=glance&amp;n=283155">Hibernate in Action</a>, chapter 8 - Writing Hibernate Applications. We'll next see where the session and/or transaction is begun and committed. </p>
<a name="WEB"></a>
<h3>BasicSample.Web for Tying it all Together</h3>

<p>As expected, the <em>BasicSample.Web</em> project contains application configuration and ASPX pages. In this sample, the code-behind pages act as controllers, communicating with the domain and data access layers directly. This is <em>not</em> best practice, MVC separation - code-behind pages should be seen as part of the view, pure and simple. But for now, it's simple, and serves well for the demonstration. (The "enterprise" sample application, discussed later, shows a better example of keeping business logic out of the code-behind pages using <a href="http://www.codeproject.com/useritems/ModelViewPresenter.asp">Model-View-Presenter</a>. <a href="http://www.castleproject.org/monorail/index.html">Castle MonoRail</a> and <a href="http://mavnet.sourceforge.net/">Maverick.NET</a> are two other options for separating logic from views, as well. There's even talk of a <a href="http://codebetter.com/blogs/jeffrey.palermo/archive/2007/03/16/Big-News-_2D00_-MVC-framework-for-ASP.NET-in-the-works-_2D00_-level-300.aspx">Microsoft-backed MVC framework in the works</a>. But I digress...)</p>

<p>Here's a closer look at some of the more interesting bits of <em>BasicSample.Web</em>...</p>

<h4>Open Session in View</h4>

<p>If you want to leverage NHibernate's lazy-loading (which you most certainly will), then the <a href="http://www.hibernate.org/43.html">Open-Session-in-View</a> pattern is the way to go. ("Session" in this context is the NHibernate <code>ISession</code>...not the ASP.NET <code>Session</code> object.) Essentially, this pattern suggests that one NHibernate session be opened per HTTP request. Although session management within the ASP.NET page life-cycle is clear in theory, various implementation approaches may be used. The approach I've taken is to create a dedicated <code>IHttpModule</code> to handle the details of the pattern. Aside from centralizing session management responsibilities, this approach provides the additional benefit that we may implement the Open-Session-in-View pattern without putting any session management code into our ASPX pages.</p>

<p>To see how this has been implemented, take a look at <em>BasicSample.Web/App_Code/NHibernateSessionModule.cs</em>. The following section is then included in <em>web.config</em> to activate the <code>IHttpModule</code>:</p>

<div class="SmallText" id="premain10" style="width: 100%; cursor: pointer;"><img preid="10" src="minus.gif" id="preimg10" height="9" width="9"><span preid="10" style="margin-bottom: 0pt;" id="precollapse10"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre10" lang="xml"><span class="code-keyword">&lt;</span><span class="code-leadattribute">httpModules</span><span class="code-keyword">&gt;</span>
  <span class="code-keyword">&lt;</span><span class="code-leadattribute">add</span> <span class="code-attribute">name</span><span class="code-keyword">="</span><span class="code-keyword">NHibernateSessionModule"</span> 
       <span class="code-attribute">type</span><span class="code-keyword">="</span><span class="code-keyword">BasicSample.Web.NHibernateSessionModule"</span> <span class="code-keyword">/</span><span class="code-keyword">&gt;</span>
<span class="code-keyword">&lt;</span><span class="code-keyword">/</span><span class="code-leadattribute">httpModules</span><span class="code-keyword">&gt;</span></pre>

<p>The <code>IHttpModule</code> opens a transaction at the beginning of a web request, and commits/closes it at the end of the request. The following is an example of modifying the <code>IHttpModule</code> so that an <code>IInterceptor</code> gets bound to the session as well as being contained within a transaction:</p>

<div class="SmallText" id="premain11" style="width: 100%; cursor: pointer;"><img preid="11" src="minus.gif" id="preimg11" height="9" width="9"><span preid="11" style="margin-bottom: 0pt;" id="precollapse11"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre11" lang="cs"><span class="code-keyword">public</span> <span class="code-keyword">void</span> Init(HttpApplication context) {
    context.BeginRequest += 
          <span class="code-keyword">new</span> EventHandler(InitNHibernateSession);
    ...
}

<span class="code-keyword">private</span> <span class="code-keyword">void</span> InitNHibernateSession(<span class="code-keyword">object</span> sender, EventArgs e) {
    IInterceptor myNHibernateInterceptor = ...

    <span class="code-comment">//</span><span class="code-comment"> Bind the interceptor to the session.</span>
    <span class="code-comment">//</span><span class="code-comment"> Using open-session-in-view, an interceptor </span>
    <span class="code-comment">//</span><span class="code-comment"> cannot be bound to an already opened session,</span>
    <span class="code-comment">//</span><span class="code-comment"> so this must be our very first step.</span>
    NHibernateSessionManager.Instance.RegisterInterceptor(
        myNHibernateInterceptor);

    <span class="code-comment">//</span><span class="code-comment"> Encapsulate the already opened session within a transaction</span>
    NHibernateSessionManager.Instance.BeginTransaction();
}</pre>

<p>Even if not used, there's very little overhead associated with opening/closing the transaction as NHibernate doesn't actually open a database connection until needed. (With that said, there's room for improvement and a point-of-susceptibility with this approach; see <a href="#WHAT_NEXT">Where to go from here?</a> for areas of further research.) Other strategies that you may want to consider are opening a session <em>not</em> associated with a transaction - hey, it <a href="http://www.martinfowler.com/bliki/Transactionless.html">works for eBay</a> - and/or registering an <code>IInterceptor</code> with the NHibernate session. (Using an <code>IInterceptor</code> is great for auditing. See <a href="http://www.amazon.com/gp/product/193239415X/102-1170069-1054529?v=glance&amp;n=283155">Hibernate in Action</a>, section 8.3.2 - Audit Logging, for more details.) </p>

<h4>NHibernate Settings Within web.config</h4>

<p>There are two key settings within <em>web.config</em> to optimize NHibernate: <code>hibernate.connection.isolation</code> and <code>hibernate.default_schema</code>. By default, NHibernate uses <code>IsolationLevel.Unspecified</code> as its database isolation level. In other words, NHibernate leaves it up to the ADO.NET provider to determine what the isolation level is by default. If the provider you're using has a default isolation level of <code>Serializable</code>, this is a very strict level of isolation that can be overkill for most application scenarios. A more reasonable setting to start with is <code>ReadCommitted</code>. With this setting, "reading transactions" don't block other transactions from accessing a row. However, an uncommitted "writing transaction" blocks all other transactions from accessing the row. Other provider defaults include (note that they are subject to change by version):</p>

<ul>
<li>SQL Server 2000 - Read Committed </li>

<li>SQL Server 2005 - Read Committed </li>

<li>Firebird - Read Committed </li>

<li>MySQL's InnoDB - Repeatable Read </li>

<li>PostgreSQL - Read Committed </li>

<li>Oracle - Read Committed </li>
</ul>

<p>The other optional setting not to be ignored, <code>hibernate.default_schema</code>, is easily overlooked, but can have a significant impact on the querying performance. By default, table names within prepared NHibernate queries - such as those from <code>CreateCriteria</code> - are not fully qualified; e.g., <code>Customers</code> vs. <code>Northwind.dbo.Customers</code>. The crux of the problem is that <em>sp_execsql</em>, the stored procedure used to execute NHibernate queries, does not efficiently optimize queries unless the table names are fully qualified. Although this is a small syntactic difference, it can slow query speeds by as much as an order of magnitude in some cases. Explicitly setting <code>hibernate.default_schema</code> can provide as much as a 33% overall performance gain on data intensive pages. The following is an example of declaring these settings in <em>web.config</em>:</p>

<div class="SmallText" id="premain12" style="width: 100%; cursor: pointer;"><img preid="12" src="minus.gif" id="preimg12" height="9" width="9"><span preid="12" style="margin-bottom: 0pt;" id="precollapse12"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre12" lang="xml"><span class="code-keyword">&lt;</span><span class="code-leadattribute">add</span> <span class="code-attribute">key</span><span class="code-keyword">="</span><span class="code-keyword">hibernate.connection.isolation"</span> <span class="code-attribute">value</span><span class="code-keyword">="</span><span class="code-keyword">ReadCommitted"</span> <span class="code-keyword">/</span><span class="code-keyword">&gt;</span>
<span class="code-keyword">&lt;</span><span class="code-leadattribute">add</span> <span class="code-attribute">key</span><span class="code-keyword">="</span><span class="code-keyword">hibernate.default_schema"</span> <span class="code-attribute">value</span><span class="code-keyword">="</span><span class="code-keyword">Northwind.dbo"</span> <span class="code-keyword">/</span><span class="code-keyword">&gt;</span></pre>

<h4>A Simple List, Add and Update Form</h4>

<p>The web project contains a few web pages:</p>

<ul>
<li><em>Default.aspx</em>: Provides the navigational homepage for the application. </li>

<li><em>ListSuppliers.aspx</em>: Fulfills the user story "User may view listing of suppliers and their products." It's a good example of using a custom collection. </li>

<li><em>ListCustomers.aspx</em>: Fulfills the user story "User may view listing of existing customers." In the enterprise sample, this page loads via Model-View-Presenter (MVP). </li>

<li><em>EditCustomer.aspx</em>: Fulfills the user stories "User may view details of customer," "User may view a listing of past orders placed by a customer," "User may view a listing of order summaries," and "User may edit customer details." Certainly a lot for one page to take on! The enterprise sample demonstrates how to split up these responsibilities using MVP and handle events coming from the views. </li>

<li><em>AddCustomer.aspx</em>: Can you guess which user story this one fulfills? </li>
</ul>

<p>The important thing to note is that the code-behind pages work with a DAO factory to talk to the database; i.e., the code isn't bound to a concrete implementation of a data access object. This makes it much easier to swap DAO implementations and unit test your code without depending on a live database. With everything in place, the following is an example of how easy it is to retrieve all the customers in the database: </p>

<div class="SmallText" id="premain13" style="width: 100%; cursor: pointer;"><img preid="13" src="minus.gif" id="preimg13" height="9" width="9"><span preid="13" style="margin-bottom: 0pt;" id="precollapse13"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre13" lang="cs">IDaoFactory daoFactory = <span class="code-keyword">new</span> NHibernateDaoFactory();
ICustomerDao customerDao = daoFactory.GetCustomerDao();
IList&lt;Customer&gt; allCustomers = customerDao.GetAll();</pre>

<p>In the above code, a concrete reference to <code>NHibernateDaoFactory</code> is retrieved via <code lang="cs"><span class="code-keyword">new</span></code>. In production code, as discussed in the <a href="#BASIC_ARCH">Architectural Notes</a>, this reference may (should?) be injected at runtime using an Inversion of Control (IoC) container such as <a href="http://www.castleproject.org/container/index.html">Castle Windsor</a>. The enterprise sample includes an example of using this utility for dependency injection. </p>

<p>While it's acceptable to use the <code lang="cs"><span class="code-keyword">new</span></code> keyword to create <code>NHiberanteDaoFactory</code> within your code-behind, or controller, your domain objects should never create DAO dependencies directly. Instead, their DAO dependencies should be provided via a public setter or via a constructor. (IoC can help here as well.) As detailed previously, this greatly enhances your ability to unit test with test double DAOs. For example, the following code, found within <em>BasicSample.Tests/Data/CustomerDaoTests.cs</em>, retrieves a customer and gives it its DAO dependency to perform the next action:</p>

<div class="SmallText" id="premain14" style="width: 100%; cursor: pointer;"><img preid="14" src="minus.gif" id="preimg14" height="9" width="9"><span preid="14" style="margin-bottom: 0pt;" id="precollapse14"> Collapse</span></div><pre style="margin-top: 0pt;" id="pre14" lang="cs">IDaoFactory daoFactory = <span class="code-keyword">new</span> NHibernateDaoFactory();
ICustomerDao customerDao = daoFactory.GetCustomerDao();

Customer customer = customerDao.GetById(Globals.TestCustomer.ID, <span class="code-keyword">false</span>);
<span class="code-comment">//</span><span class="code-comment"> Give the customer its DAO dependency via a public setter</span>
customer.OrderDao = daoFactory.GetOrderDao();</pre>

<p>Using this technique, the business layer never needs to depend directly on the data layer. Instead, it depends on interfaces defined within the same layer, as defined in the <em>BasicSample.Core</em> project.</p>
<a name="EXTENDING_BASICS"></a>
<h2>Extending the Basics to an "Enterprise" Solution</h2>

<p>What has been discussed thus far has included basic techniques for integrating NHibernate with ASP.NET and unit tests. But what has <em>not</em> been sufficiently demonstrated is the inclusion of these techniques into a scalable, reusable architecture. The <a href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices/EnterpriseSample.zip">"Enterprise" NHibernate Sample</a> demonstrates one such example and is discussed next. As "enterprise" carries many connotations, this article uses this word to describe any real-world, database backed ASP.NET application. </p>

<p>To get the enterprise sample up and running, you'll need to perform the following steps in addition to those described previously in <a href="#SAMPLE_APPS">Running the Sample Applications</a>: </p>

<ol>
<li>Unzip the enterprise sample to the folder of your choice. </li>

<li>Create a new virtual directory within IIS. The alias should be <em>EnterpriseNHibernateSample</em>, and the directory should point to the <em>EnterpriseSample.Web</em> folder that was created after unzipping the application. </li>

<li>Open <em>EnterpriseSample.Web/Config/NorthwindNHibernate.config</em> to modify the database connection string to connect to a Northwind database on Microsoft SQL Server. </li>

<li>Open the following files and change the fully qualified path, which points to <em>EnterpriseSample.Web/Config/NorthwindNHibernate.config</em>, to the corrected path on your machine: 
<ul>
<li>EnterpriseSample.Web/Web.config </li>

<li>EnterpriseSample.Web/Config/CastleComponents.config </li>

<li>EnterpriseSample.Tests/App.config </li>

<li>EnterpriseSample.Tests/Globals.cs </li>
</ul>
I don't like having to set this path in this many locations and would like to centralize it to just <em>Web.config</em> and <em>App.config</em>. See <a href="#WHAT_NEXT">Where to go from here?</a> for additional thoughts on how this could be improved. </li>

<li>Open your web browser to <em><span><a href="http://localhost/EnterpriseNHibernateSample/Default.aspx" class="smarterwiki-linkify">http://localhost/EnterpriseNHibernateSample/Default.aspx</a></span></em>, and you're off and running! </li>
</ol>
<a name="ENTERPRISE_ARCH"></a>
<h3>Real-World Architecture</h3>

<p>Although it's best to avoid <a href="http://blogs.msdn.com/ericgu/archive/2006/08/03/687962.aspx">premature generalization</a>, it's highly beneficial to begin project development with a judiciously planned architecture. A solid architectural foundation is easy to extend, establishes a clean separation of concerns, and provides built-in guidance for developers working with it. There is a fine balance between generalizing too much while still establishing a solid architecture. (I discuss this balance further in <a href="http://devlicio.us/blogs/billy_mccafferty/archive/2006/09/20/Planning-for-vs.-Reacting-to-Change.aspx">a previous post</a>.) Although one shoe does not fit all, the enterprise sample application demonstrates, what I believe to be, a solid architectural framework for medium to large sized ASP.NET projects. The general architectural structure, including direction of concrete and interface dependencies, is shown below. </p>
<img title="Application Architecture" style="width: 600px; height: 649px;" alt="Application Architecture" src="applicationarchitecture.gif" align="middle" border="0" height="649" width="600"> 
<p>High-level structure, motivations, and assumptions of this architecture are <a href="http://devlicio.us/blogs/billy_mccafferty/archive/2006/10/05/_2800_My_2900_-Default-ASP.NET-Architecture.aspx">discussed here</a>. </p>
<a name="BEYOND_BASICS"></a>
<h3>Beyond the Basics</h3>

<p>The enterprise sample extends the basic sample in the following ways: </p>

<ul>
<li><em>AbstractNHibernateDao.cs</em>, <em>NHibernateSessionManager.cs</em>, <em>NHibernateSessionModule.cs</em>, and <em>IDao.cs</em> have been placed into their own reusable/extendable project called <em>ProjectBase.Data</em>. </li>

<li><em>DesignByContract.cs</em> has been placed into their own reusable/extendable project called <em>ProjectBase.Utils</em>. </li>

<li>The can't-debug-NHibernate-without-it <a href="http://logging.apache.org/log4net/">log4net</a> has been added and is configured within <em>web.config</em>. </li>

<li>An error logging <code>IHttpModule</code> has been added to the fray. </li>

<li><em>NHibernateSessionManager.cs</em> has been "upgraded" to support concurrent use of multiple databases. Accordingly, the functionality described within the article <a href="http://www.codeproject.com/useritems/NHibernateMultipleDBs.asp">Using NHibernate with Multiple Databases</a> has been ported to the sample application. You may certainly revert it back to single database support by using code from the basic sample project. </li>

<li>The design pattern <a href="http://www.codeproject.com/useritems/ModelViewPresenter.asp">Model-View-Presenter</a> has been employed to separate business logic from <em>ListCustomers.aspx</em> and <em>EditCustomer.aspx</em>. (The version of MVP employed is in line with the definition of <a href="http://www.martinfowler.com/eaaDev/SupervisingPresenter.html">Supervising Controller</a>, an MVP specialization.) Accordingly, a new project called <em>EnterpriseSample.Presenters</em> has been created to hold view <em>interfaces</em> and presenters. Associated unit tests have also been added to <em>EnterpriseSample.Tests</em>. </li>

<li>A simple web service, <em>GetCustomer.asmx</em>, has been added which responds with DTOs populated from data retrieved by NHibernate. Please note that <strong>this example should not necessarily be considered a best practice example</strong>. I am a novice web service designer and am unsure as to what the best practices, with respect to NHibernate integration, really are. See <a href="#WHAT_NEXT">Where to go from here?</a> for an additional note concerning further research needed in this area. A number of related comments have also been included in <em>GetCustomer.cs</em>. </li>

<li><a href="http://www.castleproject.org/container/index.html">Castle Windsor</a> has been integrated to inject the DAO factory into a <a href="http://msdn2.microsoft.com/en-us/library/ms998548.aspx">Page Controller</a> for pages, user controls and web services. Keep in mind that Castle Windsor may be leveraged much further than this. </li>
</ul>

<p>Taking a close look at the example code may be daunting at first glance (and for the next couple of glances after that). But once everything's in place, it is powerful, flexible, and is minimally intrusive to the code you're developing. </p>
<a name="WHAT_NEXT"></a>
<h2>Where to go from here?</h2>

<p>If you were reading a text on an emerging technology, this section would be called "Areas for Further Research." I suppose that would be just as applicable since that's exactly what's described here. There are a few items that could be modified for better flexibility or extended for greater usability. Here are a few ideas to fill any spare time you may have:</p>

<ul>
<li>The <a href="http://msdn2.microsoft.com/en-us/teamsystem/aa718948.aspx">Guidance Automation Toolkit</a> could be leveraged to bundle these best practices into an installable base project. </li>

<li>Few best practices exist for NHibernate integration with web services. Exploring this area and defining at least "better" practices would be very beneficial to the NHibernate community. If you're interested in taking a stab at it, Thomas Erl's <a href="http://www.amazon.com/Service-Oriented-Architecture-SOA-Technology-Computing/dp/0131858580">Service-Oriented Architecture</a> is a great place to start. </li>

<li>This framework supports transactions which begin and end with the HTTP request. A more ideal scenario would be to use attributes to define when a transaction should be begun. The transaction would then commit at the end of the designated method. Using attributes would avoid a direct dependency on the <code>NHibernateSessionManager</code> class. An example attribute would be <code>[Transaction]</code> and would be placed at the top of a method. Furthermore, if working with multiple databases, the attribute would contain some sort of ID designating which database communications require a transaction, such as <code>[Transaction(<span class="code-string">"</span><span class="code-string">Primavera"</span>)]</code>. Integration with Castle Project's <a href="http://www.castleproject.org/container/facilities/trunk/atm/index.html">Automatic Transaction Management facility</a> would be a good place to start. </li>

<li>On a related note, a few developers have complained that using Open-Session-in-View, via <code>NHibernateSessionModule</code>, opens extra, unused transactions for digital assets such as images and CSS files. A discussion, and candidate solutions, may be found in the <a href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.asp?df=100&amp;forumid=278860&amp;noise=5&amp;exp=0&amp;mpp=50&amp;select=1694090&amp;fr=101#xx1694090xx">article's comments</a>. I'm interested in hearing further suggestions for cleanly resolving this occasional problem. (Using attributes to start transactions, as described in the previous point, would also fix this.) </li>

<li>The multiple database implementation passes around each database's config file location to properly identify which <code>ISession</code> belongs with which database. This results in the config file's location being duplicated in both <em>web.config</em> and in the Castle Windsor configuration file. My preference would be to get rid of this duplication, pass a simpler ID string instead, and/or eliminate needing the string to be be passed to the constructor of DAOs altogether. </li>

<li>Using the provided framework, it is not possible to manage a single transaction across two databases located on different servers. Perhaps the <em>System.Transactions</em> namespace could be leveraged to resolve this. </li>

<li>A template <a href="http://www.martinfowler.com/articles/continuousIntegration.html">Continuous Integration</a> configuration could be created for the enterprise example including <a href="http://confluence.public.thoughtworks.org/display/CCNET/Welcome+to+CruiseControl.NET">CruiseControl.NET</a>, <a href="http://nant.sourceforge.net/">NAnt</a> (or <a href="http://msdn2.microsoft.com/en-us/library/wea2sca5.aspx">MSBuild</a>), <a href="http://www.ndepend.com/">NDepend</a>, <a href="http://www.gotdotnet.com/team/fxcop/">FxCop</a>, <a href="http://www.sandcastledocs.com/">SandCastle</a>, <a href="http://www.ndbunit.org/">NDbUnit</a>, <a href="http://wesnerm.blogs.com/net_undocumented/2007/02/nstatic_present.html">NStatic</a>, and <a href="http://fit.c2.com/">FIT</a>/<a href="http://fitnesse.org/">FitNesse</a>. </li>
</ul>

<p>Please feel free to discuss your ideas for these topics in the comments below, in the <a href="http://forum.hibernate.org/viewforum.php?f=25">NHibernate forums</a>, or in a new CodeProject article! You can also contact me via <a href="http://devlicio.us/blogs/billy_mccafferty">http://devlicio.us/blogs/billy_mccafferty</a> if you'd be interested in contributing a solution to one of these topics. </p>
<a name="MIGRATING"></a>
<h2>Migrating from NHibernate 1.0x to 1.2</h2>

<p>If you're migrating from 1.0x to 1.2, you'll most definitely run into a few migration issues. The official overview of the changes to the API may be found within the <a href="http://www.hibernate.org/407.html">NHibernate 1.2 Migration Guide</a>. Listed below are a few items that you should pay particular attention to:</p>

<ul>
<li>Update all references to <code><span class="code-keyword">&lt;</span>hibernate-mapping xmlns=<span class="code-string">"</span><span class="code-string">urn:nhibernate-mapping-2.0"</span><span class="code-keyword">&gt;</span></code> with <code>urn:nhibernate-mapping-<span class="code-digit">2</span>.<span class="code-digit">2</span></code>. References may be found in HBM and config files. </li>

<li>All classes and collections with 1.2 are now loaded lazily by default. Consequently, if you run your application without modifying the lazy attribute, you'll most likely receive a number of "method <em>x</em> should be virtual." To resolve this, set <code>lazy=<span class="code-string">"</span><span class="code-string">false"</span></code> for each class and collection that you <em>do not</em> want loaded lazily. </li>

<li>Since the use of generics is now natively supported, you'll no longer need Ayende's extremely useful <a href="http://www.ayende.com/projects/nhibernate-query-analyzer/generics.aspx">NHibernate.Generics</a> utility. A detailed example of refactoring away from Ayende's NHibernate.Generics may be found at <a href="http://devlicio.us/blogs/billy_mccafferty/archive/2007/03/27/refactoring-from-ayende-s-nhibernate-generics-to-nhibernate-1-2.aspx">my blog at devlicio.us</a>. </li>
</ul>

<p>After performing any migration work to NHibernate 1.2, it's good to test the following for each parent/child relationship:</p>

<ul>
<li>Do updates to a child, via the parent, still work? </li>

<li>Do creations of new children, added to the parent, persist (or not persist) to the database as expected? </li>

<li>Do deletions of existing children from the parent, or by deleting the child directly, work correctly? </li>

<li>Have other CRUD, cascade scenarios been tested? </li>
</ul>
<a name="SUMMARY"></a>
<h2>Summary of NHibernate/ASP.NET Best Practices</h2>

<p>The following is a quick summary of the best practices conveyed within the sample application:</p>

<ul>
<li>Business objects should communicate with data access objects via interfaces; i.e., always depend on abstractions. </li>

<li>Concrete data access objects should implement interfaces defined by the "client", the business logic layer. </li>

<li>Expose data access objects via an abstract factory to assist with testing and to reduce coupling. </li>

<li>Keep NHibernate session management details out of the presentation and business logic layers. </li>

<li>Use unit test categories to easily turn off unit tests that depend on a database connection. </li>

<li>Set <code>hibernate.default_schema</code> within <em>web.config</em> to give NHibernate a great performance boost! </li>
</ul>

<p>I hope this article has helped with putting best practices into place for leveraging the benefits of ASP.NET, NHibernate, and unit testing. I'm currently having great success with this approach on my own projects, and look forward to hearing your experiences as well. Please let me know if you have any questions or suggestions. If you want to see what I'm up to at any given moment, you can always follow my latest diatribes <a href="http://devlicio.us/blogs/billy_mccafferty">here</a>. </p>

<h2>Article History</h2>

<ul>
<li>2006.03.12 - Initial posting. </li>

<li>2006.03.13 - Added <em>BasicSample.Tests</em> along with the inclusion of a mock DAO and related discussion above. </li>

<li>2006.03.28 - Clarified the default isolation level and added a plug for Model-View-Presenter. </li>

<li>2006.04.27 - Modified <code>NHibernateSessionManager</code> to store <code>ISession</code> with <code>CallContext</code> instead of <code>HttpContext</code>; updated article text to reflect changes as well. [Author's note: Bad idea!] </li>

<li>2007.04.02 - Published the 1.2<sup>nd</sup> edition of this article including compatibility with NHibernate 1.2, an expanded emphasis on test-driven development, and having updated recommendations. </li>

<li>2007.05.01 - Fixed a number of important bugs, gave <code>DomainObject</code> an overhaul, added usage of custom collections, and expanded the MVP examples. </li>
</ul>






	<!-- Main Page Contents End -->
	
	</div>
	
	
	<form name="aspnetForm" method="post" action="http://www.codeproject.com/KB/architecture/displayarticle.aspx" id="aspnetForm" style="margin: 0pt; padding: 0pt;">
<div>
<input name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTAyMTMzODg1Ng9kFgJmD2QWBAIKD2QWBAIDDw8WAh4HVmlzaWJsZWdkZAILDw8WAh8AZ2RkAgsPZBYKAgcPZBYMAgEPZBYCZg8WAh4LXyFJdGVtQ291bnQCARYCAgEPZBYEAgEPDxYCHghJbWFnZVVybAUmL3NjcmlwdC9Bd2FyZHMvSW1hZ2VzL3ByaXplX3dpbm5lci5naWZkZAIDDxYCHgRUZXh0BRIiQVNQLk5FVCBGZWIgMjAwNiJkAgMPZBYIZg8PFgIeC05hdmlnYXRlVXJsBTsvS0IvYXJjaGl0ZWN0dXJlL05IaWJlcm5hdGVCZXN0UHJhY3RpY2VzLmFzcHg/ZGlzcGxheT1QcmludGRkAgIPDxYCHwBoZGQCAw8PFgIfAGhkZAIEDw8WAh8EBSYvc2NyaXB0L0FydGljbGVzL1JlcG9ydC5hc3B4P2FpZD0xMzM5MGRkAgUPFgIeBG5hbWUFDEN1clJhdF8xMzM5MBYCZg9kFgJmD2QWAmYPZBYEAgEPZBYCAgEPDxYCHwMFGzI4OSB2b3RlcyBmb3IgdGhpcyBhcnRpY2xlLmRkAgcPZBYCZg9kFgQCAQ8PFgQfAwURUG9wdWxhcml0eTogMTEuOTkfBAUpL3NjcmlwdC9BcnRpY2xlcy9Ub3BBcnRpY2xlcy5hc3B4P3RhX3NvPTFkZAIFDxYCHwMFHFJhdGluZzogPGI+NC44NzwvYj4gb3V0IG9mIDVkAhkPZBYKAgEPZBYEAgEPFgIeCWlubmVyaHRtbAW2ATxwPlRoaXMgYXJ0aWNsZSwgYWxvbmcgd2l0aCBhbnkgYXNzb2NpYXRlZCBzb3VyY2UgY29kZSBhbmQgZmlsZXMsIGlzIGxpY2Vuc2VkIHVuZGVyIDxhIGhyZWY9Imh0dHA6Ly93d3cuY29kZXByb2plY3QuY29tL2luZm8vY3BvbDEwLmFzcHgiPlRoZSBDb2RlIFByb2plY3QgT3BlbiBMaWNlbnNlIChDUE9MKTwvYT48L3A+ZAICD2QWAgIBDxBkZBYAZAIFDxYCHwECAWQCBw8WAh8DBd8MPGgyPk90aGVyIHBvcHVsYXIgRGVzaWduIGFuZCBBcmNoaXRlY3R1cmUgYXJ0aWNsZXM6PC9oMj48dWw+PGxpPjxhIGhyZWY9Ii9LQi9hcmNoaXRlY3R1cmUvTkhpYmVybmF0ZUJlc3RQcmFjdGljZXMuYXNweCI+TkhpYmVybmF0ZSBCZXN0IFByYWN0aWNlcyB3aXRoIEFTUC5ORVQsIDEuMm5kIEVkLjwvYT48ZGl2IGNsYXNzPSJTbWFsbFRleHQiPlRoaXMgYXJ0aWNsZSBkZXNjcmliZXMgYmVzdCBwcmFjdGljZXMgZm9yIGxldmVyYWdpbmcgdGhlIGJlbmVmaXRzIG9mIE5IaWJlcm5hdGUgMS4yLCBBU1AuTkVULCBnZW5lcmljcyBhbmQgdW5pdCB0ZXN0aW5nIHRvZ2V0aGVyLjwvZGl2PjwvbGk+PGxpPjxhIGhyZWY9Ii9LQi9hcmNoaXRlY3R1cmUvZXhjZXB0aW9uYmVzdHByYWN0aWNlcy5hc3B4Ij5FeGNlcHRpb24gSGFuZGxpbmcgQmVzdCBQcmFjdGljZXMgaW4gLk5FVDwvYT48ZGl2IGNsYXNzPSJTbWFsbFRleHQiPkRlc2lnbiBndWlkZWxpbmVzIGZvciBleGNlcHRpb24gaGFuZGxpbmcgaW4gLk5FVCB3aGljaCB3aWxsIGhlbHAgeW91IHRvIGNyZWF0ZSBtb3JlIHJvYnVzdCBzb2Z0d2FyZTwvZGl2PjwvbGk+PGxpPjxhIGhyZWY9Ii9LQi9hcmNoaXRlY3R1cmUvc2luYWdhc3RvcmFnZWV4cGxvcmVyLmFzcHgiPkRlc2lnbiBQYXR0ZXJucyBJbXBsZW1lbnRhdGlvbiBpbiBhIFN0b3JhZ2UgRXhwbG9yZXIgQXBwbGljYXRpb248L2E+PGRpdiBjbGFzcz0iU21hbGxUZXh0Ij5BIGRlc2lnbiBwYXR0ZXJucyBhcHByb2FjaCBmb3IgZGVzaWduaW5nIGFuZCBleHBsYWluaW5nIGEgU3RvcmFnZSBFeHBsb3JlciBhcHBsaWNhdGlvbi4gVGhlIGFwcGxpY2F0aW9uIGlzIHVzZWQgdG8gZXhwbG9yZSBmaWxlIGNvbXBvc2l0aW9uIGluIGEgY29tcHV0ZXIgc3RvcmFnZS48L2Rpdj48L2xpPjxsaT48YSBocmVmPSIvS0IvYXJjaGl0ZWN0dXJlL01vZGVsVmlld1ByZXNlbnRlci5hc3B4Ij5Nb2RlbCBWaWV3IFByZXNlbnRlciB3aXRoIEFTUC5ORVQ8L2E+PGRpdiBjbGFzcz0iU21hbGxUZXh0Ij5UaGlzIGFydGljbGUgZGVzY3JpYmVzIHVzaW5nIHRoZSBNb2RlbC1WaWV3LVByZXNlbnRlciBwYXR0ZXJuIHdpdGhpbiBBU1AuTkVUIDIuMCB0byBlbmNvdXJhZ2UgcHJvcGVyIHNlcGFyYXRpb24gb2YgY29uY2VybnMgYmV0d2VlbiBwcmVzZW50YXRpb24gYW5kIGJ1c2luZXNzIGxvZ2ljPC9kaXY+PC9saT48bGk+PGEgaHJlZj0iL0tCL2FyY2hpdGVjdHVyZS9Nb2RlbFZpZXdDb250cm9sbGVyLmFzcHgiPkFwcGx5aW5nIFJvYnVzdG5lc3MgQW5hbHlzaXMgb24gdGhlIE1vZGVs4oCTVmlld+KAk0NvbnRyb2xsZXIgKE1WQykgQXJjaGl0ZWN0dXJlIGluIEFTUC5ORVQgRnJhbWV3b3JrLCB1c2luZyBVTUw8L2E+PGRpdiBjbGFzcz0iU21hbGxUZXh0Ij5UaGlzIGFydGljbGUgd2lsbCBlbmhhbmNlIHlvdXIgdmlzaW9uIG9uIHRoZSB1c2FnZSBvZiBSb2J1c3RuZXNzIEFuYWx5c2lzIGluIGNvbmp1bmN0aW9uIHdpdGggTW9kZWwgVmlldyBDb250cm9sbGVyLCB1c2luZyBVTUwgd2l0aCBhcHBsaWNhdGlvbiBpbiBBU1AuTkVULiBUaGlzIGFydGljbGUgaXMgYSBzZXF1ZWwgdG8gbXkgYXJ0aWNsZXMgb24gQXJjaGl0ZWN0dXJlIGFuZCBEZXNpZ24gd2l0aCBBU1AuTkVULjwvZGl2PjwvbGk+PC91bD5kAgkPDxYCHwBnZGQCCw9kFgJmD2QWAgIBD2QWAmYPZBYCZg8WBB8FBQ5SYXRlSXRlbV8xMzM5MB4FY2xhc3NlFgYCBA8WAh8AaBYCAgEPEGRkFgBkAgUPFgIfAGhkAgYPFgIfAGgWAgIBDw9kFgIeB29uY2xpY2sFI3JldHVybiByYXRlSXRlbSgxMzM5MCwyLHRydWUsdHJ1ZSk7ZAIbDw8WAh8AZ2RkAiEPFgIfAGhkAgsPDxYCHwQFJy9zY3JpcHQvQXJ0aWNsZXMvQXJ0aWNsZS5hc3B4P2FpZD0xMzM5MGRkAhEPFgIfAwULMTEgSnVuIDIwMDhkAhMPDxYEHwMFDVNlYW4gRXdpbmd0b24fBAUoL3NjcmlwdC9NZW1iZXJzaGlwL1ZpZXcuYXNweD9taWQ9Mzg3Mzg3MWRkAhUPFgIfAwUiQ29weXJpZ2h0IDIwMDYgYnkgQmlsbHkgTWNDYWZmZXJ0eWRkv8s1ZBeGHIvXsRSMRQNnYycRAyg=" type="hidden">
</div>


	
	<h2>License</h2>
	<div id="ctl00_LicenseTerms"><p>This article, along with any associated source code and files, is licensed under <a href="http://www.codeproject.com/info/cpol10.aspx">The Code Project Open License (CPOL)</a></p></div>
	
	<h2>About the Author</h2>
	
			
   
        
<table border="0" cellpadding="0" cellspacing="5" width="100%">
<tbody><tr valign="top">
<td id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberPhotoTable" style="width: 155px;" valign="top">
	<b><a id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberProfileLink" href="http://www.codeproject.com/Members/Billy-McCafferty">Billy McCafferty</a></b><br><br>
	<center></center><br>
	<span id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberType" class="SmallText">Member</span>		
</td>

<td>
	<br>	

	<table>
	<tbody><tr id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_jobTitleRow">
	<td class="SmallText" nowrap="nowrap">Occupation: </td>
	<td width="100%"><span id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberJobTitle" class="SmallText">Web Developer</span></td>
</tr>


	

	<tr id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_locationRow">
	<td class="SmallText">Location: </td>
	<td width="100%"><span id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberLocation" class="SmallText"><img src="us.gif" alt="United States" height="11px" width="16px"> United States</span></td>
</tr>

	</tbody></table>
	</td>
	</tr>
	</tbody></table>


			<br>
		
	
	<table border="0" cellpadding="0" cellspacing="0" width="100%">	
	<tbody><tr valign="top">			
		<td style="width: 100%;">
			<h2>Other popular Design and Architecture articles:</h2><ul><li><a href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx">NHibernate Best Practices with ASP.NET, 1.2nd Ed.</a><div class="SmallText">This article describes best practices for leveraging the benefits of NHibernate 1.2, ASP.NET, generics and unit testing together.</div></li><li><a href="http://www.codeproject.com/KB/architecture/exceptionbestpractices.aspx">Exception Handling Best Practices in .NET</a><div class="SmallText">Design guidelines for exception handling in .NET which will help you to create more robust software</div></li><li><a href="http://www.codeproject.com/KB/architecture/sinagastorageexplorer.aspx">Design Patterns Implementation in a Storage Explorer Application</a><div class="SmallText">A design patterns approach for designing and explaining a Storage Explorer application. The application is used to explore file composition in a computer storage.</div></li><li><a href="http://www.codeproject.com/KB/architecture/ModelViewPresenter.aspx">Model View Presenter with ASP.NET</a><div class="SmallText">This article describes using the Model-View-Presenter pattern within ASP.NET 2.0 to encourage proper separation of concerns between presentation and business logic</div></li><li><a href="http://www.codeproject.com/KB/architecture/ModelViewController.aspx">Applying Robustness Analysis on the Model–View–Controller (MVC) Architecture in ASP.NET Framework, using UML</a><div class="SmallText">This article will enhance your vision on the usage of Robustness Analysis in conjunction with Model View Controller, using UML with application in ASP.NET. This article is a sequel to my articles on Architecture and Design with ASP.NET.</div></li></ul>
		</td>
		<td>
			<iframe src="index_2.html" scrolling="no" frameborder="0" height="250px" width="300px"></iframe>						 
		</td>
	</tr>
	</tbody></table>

	<table id="ctl00_RateArticleRow" class="RatingBar" border="0" cellpadding="0" cellspacing="0" width="100%">
	<tbody><tr>
		<td><a href="#_top">Article Top</a></td>
		<td align="right"><div id="ctl00_RateArticle_RateItemWrapper" style="" name="RateItem_13390" class="">

<table cellpadding="0" cellspacing="0" width="100%">
<tbody><tr>
	
	
	<td class="voteTbl" style="white-space: nowrap;" align="right">
		<table class="">
		<tbody><tr valign="middle">
			<td id="ctl00_RateArticle_SignIn" nowrap="nowrap">
				<a href="#SignUp">Sign Up</a> to vote for this article
			</td>
		
			
			
			
			
			
			<td><span id="ctl00_RateArticle_ErrorMessage"></span></td>
		</tr>
		</tbody></table>
	</td>
</tr>
</tbody></table>

<div class="RateComDiv" id="RCD" style="display: none;">
	<table width="100%"><tbody><tr valign="top"><td align="right" width="100%">Your reason for this vote:</td>
	<td><textarea class="RateComment" rows="5" cols="60" style="width: 285px; float: right;"></textarea>
	</td></tr></tbody></table>
</div>

</div>
</td>
	</tr>
</tbody></table>

	</form>
	
	<div style="padding: 10px; overflow: hidden; margin-left: 40px; white-space: nowrap;">		  
		<a href="http://www.codeproject.com/Redir.aspx?adid=13069&amp;obid=13390&amp;obtid=2&amp;way=ban" target="_top" rel="nofollow"><img src="serveimg_002.aspx" alt="" border="0" height="60px" width="468px"></a>
		
	</div>

	<a name="_comments"></a><!-- Forum Start -->
<div id="_MessageBoard" onclick="return SwitchMessage(event, null)">
	<table id="ForumTable" class="Frm_MainTable" cellpadding="0" cellspacing="0">
		<tbody><tr>
			<td class="Frm_MsgAlert"><b>You must <a href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx%3ffid%3d278860%26df%3d90%26mpp%3d25%26noise%3d3%26sort%3dPosition%26view%3dQuick">Sign In</a> to use this message board.</b></td>
		</tr><tr>
			<td><table border="0" cellpadding="3px" cellspacing="0" width="100%">
				<tbody><tr class="Frm_HeaderRow1">
					<td style="white-space: nowrap;"><img src="forum_faq.gif" alt="FAQ" align="middle" border="0" height="16px" width="16px">&nbsp;<a href="http://www.codeproject.com/script/Forums/FAQ.aspx"><b>FAQ</b></a>&nbsp;</td><td style="white-space: nowrap; text-align: right;"><form action="http://www.codeproject.com/script/Forums/Search.aspx?fid=0" method="get" style="margin: 0pt; padding: 0pt;">
						<input name="fid" value="278860" type="hidden"><input value="" class="Frm_Input" name="kw" type="text">&nbsp;<input value="Search" name="FrmSrch" class="Frm_Button" type="submit">
					</form></td><td style="text-align: right;"></td>
				</tr><tr class="Frm_HeaderRow2">
					<td colspan="2" style="width: 100%;"><div style="text-align: right;">
						<form action="http://www.codeproject.com/script/Forums/SetOptions.aspx?floc=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx&amp;fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick" method="get" style="margin: 0pt; padding: 0pt;">
							<input name="fid" value="278860" type="hidden"><input name="currentQS" value="?floc=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx&amp;fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick" type="hidden"><input name="floc" value="/KB/architecture/NHibernateBestPractices.aspx" type="hidden">Noise Tolerance<select size="1" class="Frm_DropDown" name="noise">
								<option value="1">Very High</option><option value="2">High</option><option selected="selected" value="3">Medium</option><option value="4">Low</option><option value="5">Very Low</option>
							</select>&nbsp;&nbsp;Layout<select size="1" class="Frm_DropDown" name="view">
								<option selected="selected" value="Quick">Normal</option><option value="Topic">Expand Posts only</option><option value="Expanded">Expand Posts &amp; Replies</option><option value="Thread">Thread View</option><option value="Normal">No Javascript</option><option value="Preview">No JS + Preview</option>
							</select>&nbsp;&nbsp;Per page<select size="1" class="Frm_DropDown" name="mpp">
								<option value="10">10</option><option selected="selected" value="25">25</option><option value="50">50</option>
							</select>&nbsp;&nbsp;&nbsp;<input value="Update" name="SetOpt" class="Frm_Button" type="submit">
						</form>
					</div></td>
				</tr>
			</tbody></table></td>
		</tr><tr>
			<td><a name="xx0xx"></a><table border="0" cellpadding="2px" cellspacing="0" width="100%">
				<tbody><tr class="Frm_NavigationBar">
					<td>&nbsp;</td><td>Msgs 1 to 25 of 1,019 (Total in Forum: 1,019) (<a href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick">Refresh</a>)</td><td style="text-align: right; white-space: nowrap;"><span class="Frm_HL">First</span><span class="Frm_HL">Prev</span><a class="Frm_HL" name="Frm_HoverNL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick&amp;fr=26#xx0xx">Next</a></td>
				</tr>
			</tbody></table></td>
		</tr><tr>
			<td><table class="Frm_MsgTable" border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody><tr>
					<td><img src="t_001.gif" alt="" border="0" height="5px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd Rt HdUnSel " id="F3306457_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="16px"><a name="xx3306457xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3306457" href="http://www.codeproject.com/Messages/3306457/Thread-safety.aspx">Thread safety...</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=1317640">Craig Darin Cote</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">13:36 16 Dec '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3306457_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 16px;"><img src="t_001.gif" alt="" height="1px" width="16px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">I thought I'd share this as it might help somebody else...<br><br>I was having some issues with thread safety, and ended up making the following changes:<br><br>1. I created a superclass (named NHibernateSessionManagerThreadSafeBase to clearly indicate its purpose) and moved the following code below into it, then inherited in the NHibernateSessionManager.  The goal was to wrap and hide the semi-thread safe HashTables...<br><br><code><br><span class="code-keyword">private</span> <span class="code-keyword">const</span> <span class="code-SDKkeyword">String</span> SESSION_KEY = <span class="code-string">"</span><span class="code-string">CONTEXT_SESSION"</span>;<br><span class="code-keyword">private</span> <span class="code-keyword">const</span> <span class="code-SDKkeyword">String</span> TRANSACTION_KEY = <span class="code-string">"</span><span class="code-string">CONTEXT_TRANSACTION"</span>;<br><br><span class="code-keyword">private</span> readonly Hashtable _sessionFactories = <span class="code-keyword">new</span> Hashtable();<br><br><span class="code-keyword">protected</span> Hashtable SessionFactoriesSynchronized<br>{<br>	get { <span class="code-keyword">return</span> Hashtable.Synchronized(_sessionFactories); }<br>}<br><br><span class="code-keyword">private</span> <span class="code-keyword">static</span> Hashtable contextTransactions<br>{<br>	get<br>	{<br>		<span class="code-keyword">if</span> (isInWebContext())<br>		{<br>			<span class="code-keyword">if</span> (HttpContext.Current.Items[TRANSACTION_KEY] == null)<br>			{<br>				HttpContext.Current.Items[TRANSACTION_KEY] = <span class="code-keyword">new</span> Hashtable();<br>			}<br>				<span class="code-keyword">return</span> (Hashtable) HttpContext.Current.Items[TRANSACTION_KEY];<br>		}<br>			<span class="code-keyword">if</span> (CallContext.GetData(TRANSACTION_KEY) == null)<br>		{<br>			CallContext.SetData(TRANSACTION_KEY, <span class="code-keyword">new</span> Hashtable());<br>		}<br>			<span class="code-keyword">return</span> (Hashtable) CallContext.GetData(TRANSACTION_KEY);<br>	}<br>}<br><br><span class="code-keyword">private</span> <span class="code-keyword">static</span> Hashtable contextSessions<br>{<br>	get<br>	{<br>		<span class="code-keyword">if</span> (isInWebContext())<br>		{<br>			<span class="code-keyword">if</span> (HttpContext.Current.Items[SESSION_KEY] == null)<br>			{<br>				HttpContext.Current.Items[SESSION_KEY] = <span class="code-keyword">new</span> Hashtable();<br>			}<br>				<span class="code-keyword">return</span> (Hashtable) HttpContext.Current.Items[SESSION_KEY];<br>		}<br>			<span class="code-keyword">if</span> (CallContext.GetData(SESSION_KEY) == null)<br>		{<br>			CallContext.SetData(SESSION_KEY, <span class="code-keyword">new</span> Hashtable());<br>		}<br>			<span class="code-keyword">return</span> (Hashtable) CallContext.GetData(SESSION_KEY);<br>	}<br>}<br><br><span class="code-keyword">protected</span> <span class="code-keyword">static</span> Hashtable ContextTransactionsSynchronized<br>{<br>	get { <span class="code-keyword">return</span> Hashtable.Synchronized(contextTransactions); }<br>}<br><br><span class="code-keyword">protected</span> <span class="code-keyword">static</span> Hashtable ContextSessionsSynchronized<br>{<br>	get { <span class="code-keyword">return</span> Hashtable.Synchronized(contextSessions); }<br>}<br><br><span class="code-keyword">private</span> <span class="code-keyword">static</span> <span class="code-SDKkeyword">Boolean</span> isInWebContext()<br>{<br>	<span class="code-keyword">return</span> HttpContext.Current != null;<br>}<br></code><br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3306457" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3306457/Thread-safety.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3306457" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgRtDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd Rt HdUnSel " id="F3255745_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="16px"><a name="xx3255745xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3255745" href="http://www.codeproject.com/Messages/3255745/a-question-about-NHibernateSessionModule-and-open-.aspx">a question about NHibernateSessionModule and "open-session-in-view"</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=1881609">waynegli</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">7:09 31 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3255745_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 16px;"><img src="t_001.gif" alt="" height="1px" width="16px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">a great sample! <br><br>but when i practice, a question occurred.<br><br>the codes of NHibernateSessionManager.CloseSessionOn(..):<br>     <pre><span class="code-keyword">public</span> <span class="code-keyword">void</span> CloseSessionOn(<span class="code-keyword">string</span> sessionFactoryConfigPath)<br>        {<br>            ISession session = (ISession)ContextSessions[sessionFactoryConfigPath];<br><br>            <span class="code-keyword">if</span> (session != <span class="code-keyword">null</span> &amp;&amp; session.IsOpen)<br>            {<br>                <i><b>session.Flush();</b></i><br>                session.Close();<br>            }<br><br>            ContextSessions.Remove(sessionFactoryConfigPath);<br>        } </pre> <br><br>    because of "open-session-in-view", we will close session with this method at the end of http request.<br>"session.Flush" can do well if no NHibernateException/Sql Exception on business layer when save/update/delete entities. or, session.Flush will throw AssertionFailure exceptions sometimes.<br>    In NHibernateSessionModule,this method is in "finally{}" block, it will execute whenever we got exception or not. so the AssertionFailure may throw out. <br>     eg. "null id in entry (don't flush the Session after an exception occurs)" <br>     now i have to  close session on my own try{}catch{} blocks, but it's not a good way, i think.<br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3255745" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3255745/a-question-about-NHibernateSessionModule-and-open-.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3255745" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3263531_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="34px"><a name="xx3263531xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3263531" href="http://www.codeproject.com/Messages/3263531/Re-a-question-about-NHibernateSessionModule-and-op.aspx">Re: a question about NHibernateSessionModule and "open-session-in-view"</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=2797038">Billy McCafferty</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">13:12 6 Nov '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3263531_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 34px;"><img src="t_001.gif" alt="" height="1px" width="34px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">If you'd like to see how I handle this currently, take a look at the S#arp Architecture project at <a href="http://wiki.sharparchitecture.net/MainPage.ashx">http://wiki.sharparchitecture.net/MainPage.ashx</a>[<a href="http://wiki.sharparchitecture.net/MainPage.ashx" target="_top" title="New Window">^</a>].<br><br>Hope this helps!<br><br>Billy mcCafferty<br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3255745" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3263531/Re-a-question-about-NHibernateSessionModule-and-op.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3263531" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgRtDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd Rt HdUnSel " id="F3231557_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="16px"><a name="xx3231557xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3231557" href="http://www.codeproject.com/Messages/3231557/Please-answer.aspx">Please answer</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=1591127">Member 1591127</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">6:15 12 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3231557_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 16px;"><img src="t_001.gif" alt="" height="1px" width="16px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">Nice article  <img src="smiley_smile.gif" alt="Smile" align="top"> <br><br>From past few days i am continuously looking for ORM's/frameworks and came across many like Castle (castleproject.org),Sharp Architecture, Spring etc..I have seen many codes which uses Nhibernate and i have found dll of castle project like Castle.core and spring etc in a project having reference to Nihibernate dll. My questions are<br><br>1) Does Nhibernate is a combination of all these framework and the other framework dll’s are the part of Nhibernate framework? or we have to follow a certain path to incorporate these frameworks in Nhibernate.<br><br>2) Each framework or ORM states it's best and could be used as ORM or code modelling tool separately , so can you help me to find the best one?<br><br>As per the readings done yet i guess SharpArchitecture&gt;Nhibernate&gt;MVC where you can "&gt;" take as "better"<br>I am also confused with Microsoft Entity framework.<br><br>Could you suggest me a single framework which has best of all above frameworks(Industry best practices)?<br><br>3)Does any Nhibernate or Entity framework has the UNIT of work pattern like LLBGenPro.<br>I know that in Entity Framework they have introduced POCO but is it matured enough?<br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3231557" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3231557/Please-answer.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3231557" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3234370_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="34px"><a name="xx3234370xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3234370" href="http://www.codeproject.com/Messages/3234370/Re-Please-answer.aspx">Re: Please answer</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=2797038">Billy McCafferty</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">7:25 14 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3234370_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 34px;"><img src="t_001.gif" alt="" height="1px" width="34px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">I understand your frustration and know and can be difficult trying to figure out the best route to go.  There are many options, in none is the "best."  You need to look at each tool to determine if it's going to fit your needs and, more importantly, the needs of the project.<br><br>Your questions have a little overlap which needs to be discerned.  It looks like you're asking for three different things.  1) What's the best ORM choice, 2) what's the best IoC choice and 3) what's a good overall framework for development.<br><br>Personally, I like NHibernate best as my ORM.  It has a bigger learning curve than Entity Framework but it also provides much more power.  If you use NHibernate as your ORM, be sure to use Fluent NHibernate which wraps NHibernate in a strongly typed manner and makes it's use easier and more maintainable.  NHibernate does support the unit of work framework; simply google "nhibernate unit of work" to find out more.<br><br>As for an IoC (Inversion of Control or Dependency Injection) container, I like Castle Windsor over Spring .NET.  Spring .NET has much more to offer than Castle Windsor (or even all the Castle projects) for that matter, but Castle Windsor is a mature and simple solution to the IoC choice.<br><br>As for an overall framework, that's where S#arp Architecture comes into play.  S#arp Architecture attempts to use a very good tool selection with design pattern best practices to create a development framework for building maintainable applications on the ASP.NET MVC platform.<br><br>Hope this helps!<br>Billy McCafferty<br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3231557" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3234370/Re-Please-answer.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3234370" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3234670_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="52px"><a name="xx3234670xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3234670" href="http://www.codeproject.com/Messages/3234670/Re-Please-answer.aspx">Re: Please answer</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=1591127">Vikas Misra(TCS)</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">11:33 14 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3234670_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 52px;"><img src="t_001.gif" alt="" height="1px" width="52px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">Many Thanks Billy-McCafferty, at least you provided satisfactory reply for my questions,Yes whatever you explained i was looking for that but few more questions in queue, may be you have studied most of these framework but i cant cover up them in one go easily so ...<br><br>1) Does Nhibernate/SharpArchitecture implement Castle Windsor or Spring .NET by default or do we have to put some manual/coding effort to integrate these in our project  which built upon Nhibernate or SharpArchitecture.<br>2)I am learning Nhibernate first then i will go for sharp architecture do i need to follow this way or i could directly proceed with sharp architecture.Does it have good documentation and is it stable and safe to use right now.<br>3)Does Nhibernate/Sharp Architecture support Microsoft Ajax framework or we have to proceed with javascript based ajax techniques.<br>4)Does S#arp Architecture support Ling as for Nhibernate lot of development is in progress.<br>5) I am studying Nhibernate in Action and no doubt its not very easy, do you have any plan for a good book <br>   covering sharp architecture internals.<br> <img src="smiley_doh.gif" alt="D'Oh!" align="top"><br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3231557" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3234670/Re-Please-answer.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3234670" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3234780_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="70px"><a name="xx3234780xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3234780" href="http://www.codeproject.com/Messages/3234780/Re-Please-answer.aspx">Re: Please answer</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=2797038">Billy McCafferty</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">13:07 14 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3234780_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 70px;"><img src="t_001.gif" alt="" height="1px" width="70px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">In response to your questions:<br><br>1) S#arp Architecture comes prepackaged with Castle Windsor but could be modified to use Spring .NET.  NHibernate does not use Castle Windsor (although it does use Castle's DynamicProxy...but that's different).<br><br>2) S#arp Architecture is quite safe and stable.  What I would recommend is downloading the 1.0 RTM and then going through the documentation at <a href="http://wiki.sharparchitecture.net/MainPage.ashx">http://wiki.sharparchitecture.net/MainPage.ashx</a>[<a href="http://wiki.sharparchitecture.net/MainPage.ashx" target="_top" title="New Window">^</a>] from top to bottom.  Learning both NHibernate and Fluent NHibernate will both be necessary as well; NHibernate in Action is a good starting point.<br><br>3) I use jQuery and Ext JS for all of my AJAX support; but I believe S#arp Architecture should support Microsoft Ajax without any problem.  (See <a href="http://msdn.microsoft.com/en-us/library/dd381533.aspx">http://msdn.microsoft.com/en-us/library/dd381533.aspx</a>[<a href="http://msdn.microsoft.com/en-us/library/dd381533.aspx" target="_top" title="New Window">^</a>] for further details.)<br><br>4) If I understood the question correctly, yes, S#arp Architecture support LINQ for NHibernate.<br><br>5) I'm hoping someone will volunteer to write the book!  <img src="smiley_wink.gif" alt="Wink" align="top"><br><br>Billy<br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3231557" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3234780/Re-Please-answer.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3234780" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3235441_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="88px"><a name="xx3235441xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3235441" href="http://www.codeproject.com/Messages/3235441/Re-Please-answer.aspx">Re: Please answer</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=1591127">Vikas Misra(TCS)</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">1:52 15 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3235441_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 88px;"><img src="t_001.gif" alt="" height="1px" width="88px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">Apologies for my typing mistakes. Now I feel completely satisfied. I always feel, when Microsoft will be able to say confidently, follow “this best path and forget rest” because beginners waste lot of time initially and finally they came to know, what they studied was impractical in real scenarios.<br>Well ..Gr8 help. Once again Many Thanks Billy.<br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3231557" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3235441/Re-Please-answer.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3235441" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgRtDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd Rt HdUnSel " id="F3226615_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="16px"><a name="xx3226615xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3226615" href="http://www.codeproject.com/Messages/3226615/changes-are-not-getting-to-the-db.aspx">changes are not getting to the db</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=2402006">Yankee Imperialist Dog!</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">14:34 7 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3226615_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 16px;"><img src="t_001.gif" alt="" height="1px" width="16px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">i set up a site using the basic example and all runs ok till i attempt an update.<br><br>(debug is giving me the following on up date and cancel)<br>A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll<br>An exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll but was not handled in user code.<br>Edit : ok: <a href="http://support.microsoft.com/kb/312629">http://support.microsoft.com/kb/312629</a>[<a href="http://support.microsoft.com/kb/312629" target="_top" title="New Window">^</a>] gave me the answer to this one, but i'm still not commiting changes to the db.<br><br>Any help would be appreciated<br>thanks <br><br><div class="ForumSig">Share the knowledge. <br>I can use all the help I can get and so do YOU!<br>KES<br></div><br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3226615" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3226615/changes-are-not-getting-to-the-db.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3226615" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3227340_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="34px"><a name="xx3227340xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3227340" href="http://www.codeproject.com/Messages/3227340/Re-changes-are-not-getting-to-the-db.aspx">Re: changes are not getting to the db</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=2797038">Billy McCafferty</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">4:45 8 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3227340_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 34px;"><img src="t_001.gif" alt="" height="1px" width="34px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">Hi Yankee,<br><br>Before you get too deep into the code examples of this article, have you considered looking into its successor known as S#arp Architecture at <a href="http://wiki.sharparchitecture.net/MainPage.ashx">http://wiki.sharparchitecture.net/MainPage.ashx</a>[<a href="http://wiki.sharparchitecture.net/MainPage.ashx" target="_top" title="New Window">^</a>]?<br><br>Billy McCafferty<br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3226615" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3227340/Re-changes-are-not-getting-to-the-db.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3227340" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3227535_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="52px"><a name="xx3227535xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3227535" href="http://www.codeproject.com/Messages/3227535/Re-changes-are-not-getting-to-the-db.aspx">Re: changes are not getting to the db</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=2402006">Yankee Imperialist Dog!</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">7:19 8 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3227535_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 52px;"><img src="t_001.gif" alt="" height="1px" width="52px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">Thanks for the reply,<br>i have actually, but I'm trying to walk before i run. At this point i'm attempting to learn the mechanics of how things work. This artical seemed a good place to do just that. I see where the inserts and updates are supposed to happen, but have no idea why they are not getting committed to the db. <br><br><div class="ForumSig">Share the knowledge. <br>I can use all the help I can get and so do YOU!<br>KES<br></div><br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3226615" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3227535/Re-changes-are-not-getting-to-the-db.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3227535" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3227561_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="70px"><a name="xx3227561xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3227561" href="http://www.codeproject.com/Messages/3227561/Re-changes-are-not-getting-to-the-db.aspx">Re: changes are not getting to the db</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=2797038">Billy McCafferty</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">7:41 8 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3227561_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 70px;"><img src="t_001.gif" alt="" height="1px" width="70px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">Hi Yankee,<br><br>Could you detail all the changes you've made to the basic example?  Did everything work "out of the box" after changing the appropriate configuration settings?<br><br>Billy McCafferty<br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3226615" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3227561/Re-changes-are-not-getting-to-the-db.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3227561" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3227628_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="88px"><a name="xx3227628xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3227628" href="http://www.codeproject.com/Messages/3227628/Re-changes-are-not-getting-to-the-db.aspx">Re: changes are not getting to the db</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=2402006">Yankee Imperialist Dog!</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">8:27 8 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3227628_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 88px;"><img src="t_001.gif" alt="" height="1px" width="88px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">(i appreciate this, thanks!)<br>Everything worked out of the box after i changed the connection strings to by version of Northwind: (sql2k8, standard, sql authentication, just to be simple i'm using sa. the dialect, 2k5, as far as i know should work ok.) I've setup a website instead of a virtural directory running on 127.0.0.1:58456, vista/iis.<br>On list i get all customers and suppliers. When i run the page on update i'm attaching to process for debug.<br><br>again thanks, i appreciate this. If this follows my usual pattern the "issues" will be a minor. I often say of my mistakes, "If i didn't have dumb mistakes, i'd have no mistakes at all!"<br><br>KES <br><br><div class="ForumSig">Share the knowledge. <br>I can use all the help I can get and so do YOU!<br>KES<br></div><br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3226615" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3227628/Re-changes-are-not-getting-to-the-db.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3227628" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3227639_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="106px"><a name="xx3227639xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3227639" href="http://www.codeproject.com/Messages/3227639/Re-changes-are-not-getting-to-the-db.aspx">Re: changes are not getting to the db</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=2797038">Billy McCafferty</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">8:33 8 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3227639_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 106px;"><img src="t_001.gif" alt="" height="1px" width="106px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">I have not tried this implementation on Vista/IIS and can't vouch for it's compatibility in that environment.  If you're interested in ultimately going towards S#arp Architecture, I would give this article a cursory read and then dig into the links found under the "New to S#arp Architecture?" section at <a href="http://wiki.sharparchitecture.net/">http://wiki.sharparchitecture.net/</a>[<a href="http://wiki.sharparchitecture.net/" target="_top" title="New Window">^</a>].<br><br>I apologize for not having a more definitive resolution for the issue you're running into.<br><br>Billy McCafferty<br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3226615" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3227639/Re-changes-are-not-getting-to-the-db.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3227639" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3227651_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="116px"><a name="xx3227651xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3227651" href="http://www.codeproject.com/Messages/3227651/Re-changes-are-not-getting-to-the-db.aspx">Re: changes are not getting to the db</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=2402006">Yankee Imperialist Dog!</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">8:42 8 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3227651_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 116px;"><img src="t_001.gif" alt="" height="1px" width="116px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">that's ok, your time on this was appreciated. If i do figure it out i'll post the reason here.<br>Thanks<br>KES <br><br><div class="ForumSig">Share the knowledge. <br>I can use all the help I can get and so do YOU!<br>KES<br></div><br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3226615" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3227651/Re-changes-are-not-getting-to-the-db.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3227651" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3227709_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="126px"><a name="xx3227709xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3227709" href="http://www.codeproject.com/Messages/3227709/Re-changes-are-not-getting-to-the-db.aspx">Re: changes are not getting to the db</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=2402006">Yankee Imperialist Dog!</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">9:31 8 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3227709_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 126px;"><img src="t_001.gif" alt="" height="1px" width="126px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">I was able to get it to update by including customerDao.CommitChanges();<br>in the  private void UpdateCustomer(). This leads me to think i discovered the problem. the httpModule: <add name="NHibernateSessionModule" type="BasicSample.Web.NHibernateSessionModule"> is not being registered. When i set a break point on the methods they are not firing. I'll keep looking on why the code file is not found. <br><br><div class="ForumSig">Share the knowledge. <br>I can use all the help I can get and so do YOU!<br>KES<br></div><br></add></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3226615" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3227709/Re-changes-are-not-getting-to-the-db.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3227709" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3227712_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="136px"><a name="xx3227712xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3227712" href="http://www.codeproject.com/Messages/3227712/Re-changes-are-not-getting-to-the-db.aspx">Re: changes are not getting to the db</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=2797038">Billy McCafferty</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">9:32 8 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3227712_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 136px;"><img src="t_001.gif" alt="" height="1px" width="136px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">Wow, nicely done!<br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3226615" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3227712/Re-changes-are-not-getting-to-the-db.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3227712" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3227750_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="146px"><a name="xx3227750xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3227750" href="http://www.codeproject.com/Messages/3227750/Re-changes-are-not-getting-to-the-db.aspx">Re: changes are not getting to the db</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=2402006">Yankee Imperialist Dog!</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">10:04 8 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3227750_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 146px;"><img src="t_001.gif" alt="" height="1px" width="146px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">lol, well, it wasn't the best solution.<br><img src="smiley_wink.gif" alt="Wink" align="top"> The deal is I need figure out to get the handler reconized. I really like how that's supposed to works. I've not done many of those. I've created a seprate project and am attempting to reference it that way. That's kind of the hammer approach, but still can't seem to get it to understand that it's supposed to fire.<br><br>(and thanks again!) <br><br><div class="ForumSig">Share the knowledge. <br>I can use all the help I can get and so do YOU!<br>KES<br></div><br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3226615" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3227750/Re-changes-are-not-getting-to-the-db.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3227750" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HdUnSel " id="F3227760_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="156px"><a name="xx3227760xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3227760" href="http://www.codeproject.com/Messages/3227760/Re-changes-are-not-getting-to-the-db.aspx">Re: changes are not getting to the db</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=2402006">Yankee Imperialist Dog!</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">10:10 8 Oct '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3227760_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 156px;"><img src="t_001.gif" alt="" height="1px" width="156px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">i said handler, .. i ment Module... (it would help if i knew what the hell i was talking about) <br><br><div class="ForumSig">Share the knowledge. <br>I can use all the help I can get and so do YOU!<br>KES<br></div><br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3226615" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3227760/Re-changes-are-not-getting-to-the-db.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3227760" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgRtDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd Rt HdUnSel " id="F3091714_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="16px"><a name="xx3091714xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3091714" href="http://www.codeproject.com/Messages/3091714/Please-Help-Me-sir-Regarding-web-config-Error.aspx">Please Help Me  sir ,Regarding web.config Error</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=4120341">RAKESH gaur mkcl</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">22:52 22 Jun '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3091714_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 16px;"><img src="t_001.gif" alt="" height="1px" width="16px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">Hello Sir.Please Help Me <br>I am new in Nhibernate with Asp .Net.<br><br><br>MyFolder Structer is <br>in D Drive :<br>D:\online\OES<br>in this some folder like <br>OES.DAO---it is a Class libabrary <br>OnlineExam---It Is website in Asp .Net<br>and My solution File OES.sln<br><br>Tecnology used is VS2005,Nhibernate,Asp .Net,AJAX<br>I develope A Arcitectuer in which two layer .<br>One is website layer and one is my Class libarary whic name is OES.DAO.<br>OES.DAO CONTAION ALL BUSINESS logic.<br><br><br><b>OES.DAO CLASS LIABARY CONTAION SOME FOLDER</b><br>ONE OF THEM IS<br>1.dblayer: it contaion one class <br>which code is <br><br><br><br>using System;<br>using System.Collections;<br>using System.Web;<br>using NHibernate;<br>using NHibernate.Cfg;<br>using Iesi.Collections;<br>using OES.DAO.businessobjects;<br>using OES.DAO.util;<br><br>namespace OES.DAO.dblayer<br>{<br>   /// &lt;summary&gt;<br>   /// This is the main class for accessing the database via the NHibernate O/R mappings.<br>   /// The middle tier should use this class for DB access!<br>   ///<br>   /// The usage of this class is along the lines of:<br>   /// 1. Call BeginDBWork() and use the session it returns for DP operations<br>   /// 2. Call EndDBWork() - commits the transaction frees resources etc.<br>   ///<br>   /// The above methods are to be called by the application at start/end of<br>   /// processing a request. Individual ASP.NET pages are expected to use<br>   /// GetCurrentSession() to work on their data!<br>   ///<br>   /// &lt;/summary&gt;<br>   public class DBFacade<br>   {<br><br>      private const string SessionHTTPContextKey = "itexampractice-context_session";<br>      private const string TransactionHTTPContextKey = "itexampractice-context_transaction";<br>      <br>      private static readonly ISessionFactory sessionFactory;<br>      <br>      private static readonly bool runningInMonoOnUnix;<br>      private static readonly bool runningInMSDOTNET;<br>      <br>      /// &lt;summary&gt;<br>      /// Initialization method for the DB facade. Gor now it is a dummy since the static <br>      /// initializer does the work<br>      /// &lt;/summary&gt;   <br>      public static void Init()<br>      {<br>         // ...<br>      }<br><br>      static DBFacade()<br>      {<br><br>          <br>            [color=#FF4040]sessionFactory = new Configuration().Configure().BuildSessionFactory();[/color]          Log.Info("DB Facade being initilaized, Platform: " + OSInfo.PlatformName);<br>          runningInMSDOTNET = OSInfo.PlatformIsWindows;<br>          runningInMonoOnUnix = OSInfo.PlatformIsASortOfUnix;<br>          <br>          if (runningInMonoOnUnix)<br>          {<br>             // TODO: Maybe special init code .. if necessary<br>          };<br>      }<br>      <br>      /// &lt;summary&gt;<br>      /// Opens a new session for woring with the database. At the same time starts<br>      /// a new transaction. The session and transaction are saved under the server's <br>      /// HTTP context. The session object is returned for subsequent operations<br>      /// &lt;/summary&gt;      <br>      public static ISession BeginDBWork()<br>      {<br>          HttpContext context = HttpContext.Current;<br>          ISession currentSession = context.Items[SessionHTTPContextKey] as ISession;<br>          ITransaction currentTransaction = context.Items[TransactionHTTPContextKey] as ITransaction;<br>          <br>          if ((currentSession == null) &amp;&amp; (currentTransaction == null))<br>          {<br>              currentSession = sessionFactory.OpenSession();<br>              context.Items[SessionHTTPContextKey] = currentSession;<br>              <br>              currentTransaction = currentSession.BeginTransaction();<br>              context.Items[TransactionHTTPContextKey] = currentTransaction;<br>          } else<br>         {<br>            // TODO: Close sesion and transaction<br>            <br>             // No current session<br>             throw new SystemException(<br>               "It seems someone is trying to open an NHibernate session, although " +<br>               "one is already open!");<br>         }<br>          <br>          return currentSession;<br>      }<br>      <br>      /// &lt;summary&gt;<br>      /// Returns the previosly opened session. Throws exception if it is not open!<br>      /// &lt;/summary&gt;      <br>      public static ISession GetCurrentSession()<br>      {<br>         HttpContext context = HttpContext.Current;<br>          ISession currentSession = context.Items[SessionHTTPContextKey] as ISession;<br>         <br>         if (currentSession == null)<br>         {<br>            // No current session<br>            throw new SystemException(<br>               "It seems someone is trying to get a NHibernate session, although " +<br>               "one is NOT currently open!");<br>         }<br>         <br>         return currentSession;<br>      }      <br>      <br>      /// &lt;summary&gt;<br>      /// Starts a new transaction within the same session. May be used when we have<br>      /// processing spanning several transactions.<br>      /// For convenience returns the session.<br>      /// &lt;/summary&gt;      <br>        public static ISession StartNewTransaction()<br>        {<br>            HttpContext context = HttpContext.Current;<br>            ISession currentSession = context.Items[SessionHTTPContextKey] as ISession;<br>            ITransaction currentTransaction = context.Items[TransactionHTTPContextKey] as ITransaction;<br>         <br>         if ((currentSession == null) || (currentTransaction == null))<br>         {<br>             // No current session<br>             throw new SystemException("Starting new transaction but no session exists!");<br>         }<br>         <br>         currentSession.Flush();<br>         // TODO: This is a workaround for problems with Mono and ADO.NET<br>         // transactions. The bug is expected to be fixed in Mono in early<br>         // 2008! <br>         try<br>         {<br>            currentTransaction.Commit();<br>         } catch (Exception e)<br>         {<br>            if ((!(e is NullReferenceException)) || runningInMSDOTNET)<br>            {<br>               throw e;<br>            } else // NullRef in Mono<br>            {<br>               Log.Warning("DBFacade: Ignoring NullReferenceException - " + <br>                           "Workround for a Mono bug (versions prior to 1.2.6) " +<br>                        "with ADO.NET transactions!");<br>            }<br>         }<br><br>         // Start a new transaction here<br>           currentTransaction = currentSession.BeginTransaction();<br>           context.Items[TransactionHTTPContextKey] = currentTransaction;<br>         <br>         return currentSession;<br>      }<br><br>      /// &lt;summary&gt;<br>      /// Ends a previously opened session. Commits the current transactions and<br>      /// closes the session.<br>      /// &lt;/summary&gt;      <br>        public static void EndDBWork()<br>        {<br>            HttpContext context = HttpContext.Current;<br>            ISession currentSession = context.Items[SessionHTTPContextKey] as ISession;<br>            ITransaction currentTransaction = context.Items[TransactionHTTPContextKey] as ITransaction;<br>         <br>         if ((currentSession == null) || (currentTransaction == null))<br>         {<br>             // No current session<br>             throw new SystemException("Ending DB work but no session exists!");<br>         }<br>         <br>         try<br>         {<br>            currentSession.Flush();<br>            // TODO: This is a workaround for problems with Mono and ADO.NET<br>            // transactions. The bug is expected to be fixed in Mono in early<br>            // 2008! <br>            try<br>            {<br>               currentTransaction.Commit();<br>            } catch (Exception e)<br>            {<br>               if ((!(e is NullReferenceException)) || runningInMSDOTNET)<br>               {<br>                  throw e;<br>               } else // NullRef in Mono<br>               {<br>                  Log.Warning("DBFacade: Ignoring NullReferenceException - " + <br>                              "Workround for a Mono bug (versions prior to 1.2.6) " +<br>                           "with ADO.NET transactions!");<br>               }<br>            }<br>         } finally<br>         {<br>            context.Items.Remove(SessionHTTPContextKey);<br>            context.Items.Remove(TransactionHTTPContextKey);<br>            <br>            // TODO: Close the session in any case - to start clean!<br>            currentSession.Close();<br>         };<br>      }<br><br>      /// &lt;summary&gt;<br>      /// Releases all NHibernate resources for DB oprations. To be called at the<br>      /// exit of the Web application.<br>      /// &lt;/summary&gt;      <br>      public static void CloseSessionFactory()<br>      {<br>          if (sessionFactory != null)<br>          {<br>              sessionFactory.Close();<br>          }<br>      }<br>      <br>   }<br>}<br><br><br><br><br><br>Here I Got Error sessionFactory = new Configuration().Configure().BuildSessionFactory();<br><br><br>2.Thesecond FOLDER in OES.DAO IS businessobjects<br>WHICH CONTAION the all classes which map the database Tables.<br><br><br>Now In My Fisrt Layer whic name is OnlineExam [It is website] and My Solution File name is OES.<br><br>The Mapping hb.xml Files in dbmappings Folderls which map Database tables one of then is <br>AnswerToMCQuestion.hbm.xml<br><br><br>Code:<br>&lt;?xml version="1.0" encoding="utf-8" ?&gt;<br><br><br>&lt;hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"<br>    namespace=" OES.DAO.businessobjects" assembly="OES.DAO" &gt;<br>    &lt;class name="AnswerToMCQuestion" table="tAnswerToMCQuestion"&gt;<br>        &lt;id name="Id"&gt;<br>            &lt;column name="cId"/&gt;<br>            &lt;generator class="uuid.hex" /&gt;<br>        &lt;/id&gt;<br>        &lt;property name="CreationDateTicks"&gt;<br>            &lt;column name="cCreationDateTicks"/&gt;<br>        &lt;/property&gt;<br>        &lt;property name="IsRightAsInt"&gt;<br>            &lt;column name="cIsRight"/&gt;<br>        &lt;/property&gt;<br>        &lt;property name="AnswerText"&gt;<br>            &lt;column name="cAnswerText"/&gt;<br>        &lt;/property&gt;<br>        &lt;property name="NumInOrder"&gt;<br>            &lt;column name="cNumInOrder"/&gt;<br>        &lt;/property&gt;<br>      &lt;many-to-one <br>         name="Question" <br>         class="MultipleChoiceExamQuestion" <br>         column="cQuestionId" <br>         not-null="true"/&gt;<br><br>    &lt;/class&gt;<br>&lt;/hibernate-mapping&gt;<br><br><br><br><br>Now The main Thing is Web.Config file setting where I got Error bz i dont know how to Map these .HBM.XML File here and how i give The Path bz My Business logic table which map the database tables in OES.DAO layesr .<br><br><br><br>Code:<br><br>&lt;?xml version="1.0"?&gt;<br>&lt;configuration&gt;<br>   &lt;configSections&gt;<br>      &lt;sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"&gt;<br>         &lt;sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"&gt;<br>            &lt;section name="scriptResourceHandler"  type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/&gt;<br>        &lt;sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"&gt;<br>          &lt;section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere"/&gt;<br>               &lt;section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/&gt;<br>               &lt;section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/&gt;<br>            &lt;/sectionGroup&gt;<br>         &lt;/sectionGroup&gt;<br>      &lt;/sectionGroup&gt;<br>      &lt;section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" /&gt;<br>   &lt;/configSections&gt;<br><br><br><br>    &lt;hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"    &gt;<br>      &lt;session-factory &gt;<br>         &lt;!-- SECTION TO BE CHANGED DEPENDING ON DATABASE AND RUNTIME ENVIRONMENT --&gt;<br>         &lt;property name="dialect"&gt;NHibernate.Dialect.MsSql2000Dialect&lt;/property&gt;<br>         &lt;property name="connection.provider"&gt;NHibernate.Connection.DriverConnectionProvider&lt;/property&gt;<br>         &lt;property name="connection.connection_string"&gt;Data Source=.;Initial Catalog=sd;User ID=sa;Password=sa;&lt;/property&gt;<br>         &lt;property name="connection.driver_class"&gt;NHibernate.Driver.SqlClientDriver&lt;/property&gt;<br>         &lt;property name="show_sql"&gt;false&lt;/property&gt;<br><br>      [b]<br>      &lt;mapping resource="../config/common/dbmappings/User.hbm.xml"    assembly="OES" /&gt;<br>      &lt;mapping resource="../config/common/dbmappings/QuestionComment.hbm.xml"  assembly="OES"/&gt;<br>      &lt;mapping resource="../config/common/dbmappings/QuestionRating.hbm.xml"  assembly="OES" /&gt;<br>      &lt;mapping resource="../config/common/dbmappings/TestExamination.hbm.xml" assembly="OES" /&gt;<br>      &lt;mapping resource="../config/common/dbmappings/Exam.hbm.xml" assembly="OES"  /&gt;<br>      &lt;mapping resource="../config/common/dbmappings/ExamSection.hbm.xml" assembly="OES" /&gt;<br>      &lt;mapping resource="../config/common/dbmappings/Vote.hbm.xml" assembly="OES" /&gt;<br>         &lt;mapping resource="../config/common/dbmappings/VoteByLink.hbm.xml" assembly="OES" /&gt;<br>      &lt;mapping resource="../config/common/dbmappings/ExamQuestion.hbm.xml" assembly="OES" /&gt;<br>         &lt;mapping resource="../config/common/dbmappings/AnswerToMCQuestion.hbm.xml" assembly="OES" /&gt;[/b]<br><br>    &lt;/session-factory&gt;<br><br>  &lt;/hibernate-configuration&gt;<br><br><br><br><br>  &lt;system.web&gt;<br>      &lt;!--&lt;trust level="Medium"/&gt;--&gt;<br>      &lt;httpRuntime executionTimeout="1000" maxRequestLength="250000"/&gt;<br>      &lt;!--&lt;sessionState mode="InProc" cookieless="false" timeout="180"/&gt;--&gt;<br>      &lt;httpHandlers&gt;<br>         &lt;remove verb="*" path="*.asmx"/&gt;<br>         &lt;add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/&gt;<br>         &lt;add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/&gt;<br>         &lt;add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/&gt;<br>      &lt;/httpHandlers&gt;<br>      &lt;httpModules&gt;<br>         &lt;add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/&gt;<br>      &lt;/httpModules&gt;<br>      &lt;globalization culture="en-us" uiCulture="en"/&gt;<br>      &lt;compilation debug="true"&gt;<br>         &lt;assemblies&gt;<br>        <br>            &lt;add assembly="System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/&gt;<br>            &lt;add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/&gt;<br>            &lt;add assembly="System.Web.Extensions.Design, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/&gt;<br>            &lt;add assembly="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/&gt;<br>            &lt;add assembly="System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/&gt;&lt;/assemblies&gt;<br>      &lt;/compilation&gt;<br>      &lt;!--&lt;authentication mode="Forms"&gt;<br>         &lt;forms loginUrl="Login.aspx"/&gt;<br>      &lt;/authentication&gt;--&gt;<br>      &lt;authorization&gt;<br>         &lt;allow users="*"/&gt;<br>      &lt;/authorization&gt;<br>      &lt;customErrors mode="Off"&gt;<br>      &lt;/customErrors&gt;<br>      &lt;pages&gt;<br>         &lt;controls&gt;<br>            &lt;add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/&gt;<br>         &lt;/controls&gt;<br>      &lt;/pages&gt;<br>   &lt;/system.web&gt;<br>   &lt;!--&lt;system.webServer&gt;<br>      &lt;validation validateIntegratedModeConfiguration="false"/&gt;<br>      &lt;modules&gt;<br>         &lt;add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/&gt;<br>      &lt;/modules&gt;<br>      &lt;handlers&gt;<br>         &lt;remove name="WebServiceHandlerFactory-Integrated"/&gt;<br>         &lt;add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/&gt;<br>         &lt;add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/&gt;<br>         &lt;add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/&gt;<br>      &lt;/handlers&gt;<br>   &lt;/system.webServer&gt;--&gt;<br>&lt;/configuration&gt;<br><br><br><br><br><br>In Mapping Tag i dont understand How I give The Path .<br>which Assempbly path I give .How I give the .HBM.XML File Path .<br><br>Please Help me All professionls .I am New In Nhibernate <br>I wam waiting For Replies.<br><br>Rakesh Gaur<br>mkclrakesh@gmail.com<br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3091714" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3091714/Please-Help-Me-sir-Regarding-web-config-Error.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3091714" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgRtDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd HiVote Rt HdUnSel " id="F3077412_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="16px"><a name="xx3077412xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3077412" href="http://www.codeproject.com/Messages/3077412/BeginTransaction-commented.aspx">BeginTransaction commented</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=3309934">santinpierluigi</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">9:29 11 Jun '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3077412_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 16px;"><img src="t_001.gif" alt="" height="1px" width="16px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">why in the enterprise sample, the code inside BeginTransaction in SessionModule is commented?<br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3077412" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3077412/BeginTransaction-commented.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3077412" style="white-space: nowrap;">5.00/5 (2 votes) </span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgRtDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd Rt HdUnSel " id="F3056141_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="16px"><a name="xx3056141xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3056141" href="http://www.codeproject.com/Messages/3056141/Great-Article.aspx">Great Article!</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=497846">Sandeep Aparajit</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">1:39 27 May '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3056141_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 16px;"><img src="t_001.gif" alt="" height="1px" width="16px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">Thanks for such a fantastic article! <br><br><div class="ForumSig">Sandeep Aparajit <br>Mark usefull posts as Helpful/Answers.<br><a href="http://aparajit.co.in/">Home</a> | <a href="http://sandeep-aparajit.blogspot.com/">Technical articles on C#, ASP.NET, Architecture and Security</a> | <a href="http://photos.aparajit.co.in/">Photography</a></div><br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3056141" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3056141/Great-Article.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3056141" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgRtDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd Rt HdUnSel " id="F3054915_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="16px"><a name="xx3054915xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3054915" href="http://www.codeproject.com/Messages/3054915/rollback-on-business-exception.aspx">rollback on business exception</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=6239450">valentinog</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">5:57 26 May '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3054915_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 16px;"><img src="t_001.gif" alt="" height="1px" width="16px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">hi all.<br><br>I've a question about the NHibernateSessionModule class.<br><br>How can I rollback a transaction in the HttpModule when a business exception arises? <br><pre><br><span class="code-comment">//</span><span class="code-comment"> Business code<br></span>DaoFactory daoFactory = <span class="code-keyword">new</span> DaoFactory(<span class="code-string">"</span><span class="code-string">path.to.config.file"</span>);<br>ObjADao bizObjADao = daoFactory.GetObjADao();<br>ObjBDao bizObjBDao = daoFacotry.GetObjBDao();<br><br>ObjA oA = <span class="code-keyword">new</span> ObjA();<br>ObjADao.Create(oA);<br><br>ObjB oB = <span class="code-keyword">new</span> ObjB(); <span class="code-keyword">&lt;</span>--- <span class="code-keyword">for</span> some reason, <span class="code-keyword">this</span> op throws an exception. I need to rollback the previous create<br>ObjBDao.Create(oB);<br></pre><br><br>In the HttpModule I can check for HttpContext.Current.Server.GetLastError() and then rollback<br><br>Is this right or there is a better way?<br><br>thanks for your attention<br><br>[edit]<br>PS<br><br>where ObjB oB = new ObjB(); works but ObjBDao.Create(oB); fails, how can I notify it to the http module for rollback?<br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3054915" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3054915/rollback-on-business-exception.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3054915" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgRtDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd Rt HdUnSel " id="F3051867_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="16px"><a name="xx3051867xx"></a><img src="msg_question.gif" alt="Question" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3051867" href="http://www.codeproject.com/Messages/3051867/Deploying-Publish-absolute-paths-in-config-file.aspx">Deploying/Publish absolute paths in config file?</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=3314747">bvillanu</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">12:31 22 May '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3051867_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 16px;"><img src="t_001.gif" alt="" height="1px" width="16px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">Hi, I'm new at using NH and Castle. I was wondering what to do about the absolute paths in the config files when I deploy/publish (I'm still confused on difference of those) to a hosting service? Or in other words, what would I need to do to go from development to putting the sample on the production server?<br><br>I don't want to tell my managers, "It works on my computer", even though I'm sure that excuse is often used.<br><br>Thanks.<br>-Bernard<br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3051867" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3051867/Deploying-Publish-absolute-paths-in-config-file.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3051867" style="white-space: nowrap;"></span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr class="Quick">
					<td class="Frm_MsgRtDivide"><img src="t_001.gif" alt="" border="0" height="1px" width="1px"></td>
				</tr>
<!-- Start Message head -->

				<tr class="MsgHd LoVote Rt HdUnSel " id="F3050593_h0">
					<td width="100%"><table class="QuickHd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" width="16px"><a name="xx3050593xx"></a><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"></td><td class="Frm_MsgSubject"><a id="DynMessLink" name="3050593" href="http://www.codeproject.com/Messages/3050593/.aspx">..</a> <a onclick="return Pin(this);" href="#" title="Click to pin message"><img src="pin.gif" alt="Pin" align="top" border="0" height="12px" width="13px"></a></td><td style="width: 20px; white-space: nowrap;"><img src="member_sm.gif" title="member" alt="member" border="0" height="16px"></td><td class="Frm_MsgAuthor"><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=6209079">desirejoy</a></td><td class="Frm_MsgDate" style="vertical-align: top; white-space: nowrap;">12:36 21 May '09 &nbsp;</td>
						</tr>
					</tbody></table></td>
				</tr><!-- End Message head -->

				<tr id="F3050593_h1" style="display: none;">
					<td width="100%"><table class="QuickBd" border="0" cellpadding="0" cellspacing="0" width="100%">
						<tbody><tr>
							<td class="Frm_MsgIndent" style="width: 16px;"><img src="t_001.gif" alt="" height="1px" width="16px"></td><td class="MsgBd BdSel "><table border="0" cellpadding="0" cellspacing="5px" width="100%">
								<tbody><tr>
									<td><table border="0" cellpadding="0" cellspacing="0" width="100%">
										<tbody><tr>
											<td colspan="2">thank you <img src="smiley_smile.gif" alt="Smile" align="top"> <br><br><div class="ForumSig"><a href="http://www.theporn.tk/" title="the porn">the porn</a> <a href="http://www.xfreepornmovies.com/" title="free porn">free porn</a> <a href="http://www.etek6.org/" title="porno izle">porno izle</a> <a href="http://www.xyouporn.net/" title="You Porn">You Porn</a> <a href="http://sexizle.tk/" title="sex izle">Sex izle</a></div><br></td>
										</tr><tr style="vertical-align: middle;">
											<td class="Frm_MsgFt"><a class="Frm_MHL" href="http://www.codeproject.com/script/Membership/LogOn.aspx?rp=%2fKB%2farchitecture%2fNHibernateBestPractices.aspx">Sign In</a>·<a class="Frm_MHL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;sort=Position&amp;tid=3050593" title="View&nbsp;Thread">View&nbsp;Thread</a>·<a class="Frm_MHL" href="http://www.codeproject.com/Messages/3050593/.aspx" title="Get permanent link">PermaLink</a></td><td class="Frm_MsgFt" style="text-align: right;"><span id="MVF3050593" style="white-space: nowrap;">1.00/5 (3 votes) </span></td>
										</tr>
									</tbody></table></td>
								</tr>
							</tbody></table></td>
						</tr>
					</tbody></table></td>
				</tr><tr>
					<td><img src="t_001.gif" alt="" border="0" height="5px" width="1px"></td>
				</tr>
			</tbody></table></td>
		</tr><tr>
			<td><table cellpadding="2px" cellspacing="0" width="100%">
				<tbody><tr class="Frm_Footer">
					<td>Last Visit: 15:49 16 Jan '10  &nbsp; &nbsp; Last Update: 15:49 16 Jan '10 </td><td style="text-align: right; white-space: nowrap;"><input id="_mbnUrl" value="/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick&amp;fr=26" type="hidden"><b>1</b><a class="Frm_HL" name="Frm_HoverNL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick&amp;fr=26#xx0xx">2</a><a class="Frm_HL" name="Frm_HoverNL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick&amp;fr=51#xx0xx">3</a><a class="Frm_HL" name="Frm_HoverNL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick&amp;fr=76#xx0xx">4</a><a class="Frm_HL" name="Frm_HoverNL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick&amp;fr=101#xx0xx">5</a><a class="Frm_HL" name="Frm_HoverNL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick&amp;fr=126#xx0xx">6</a><a class="Frm_HL" name="Frm_HoverNL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick&amp;fr=151#xx0xx">7</a><a class="Frm_HL" name="Frm_HoverNL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick&amp;fr=176#xx0xx">8</a><a class="Frm_HL" name="Frm_HoverNL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick&amp;fr=201#xx0xx">9</a><a class="Frm_HL" name="Frm_HoverNL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick&amp;fr=226#xx0xx">10</a><a class="Frm_HL" name="Frm_HoverNL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick&amp;fr=251#xx0xx">11</a> <a class="Frm_HL" name="Frm_HoverNL" href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx?fid=278860&amp;df=90&amp;mpp=25&amp;noise=3&amp;sort=Position&amp;view=Quick&amp;fr=26#xx0xx">Next »</a></td>
				</tr>
			</tbody></table></td>
		</tr>
	</tbody></table>
</div><p class="SmallText"><img src="msg_general.gif" alt="General" align="top" height="16px" width="16px"> General &nbsp;&nbsp; <img src="msg_news.gif" alt="News" align="top" height="16px" width="16px"> News &nbsp;&nbsp; <img src="msg_question.gif" alt="Question" align="top" height="16px" width="16px"> Question &nbsp;&nbsp; <img src="msg_answer.gif" alt="Answer" align="top" height="16px" width="16px"> Answer &nbsp;&nbsp; <img src="msg_joke.gif" alt="Joke" align="top" height="16px" width="16px"> Joke &nbsp;&nbsp; <img src="msg_rant.gif" alt="Rant" align="top" height="16px" width="16px"> Rant &nbsp;&nbsp; <img src="msg_admin.gif" alt="Admin" align="top" height="16px" width="16px"> Admin &nbsp;&nbsp; </p>
<!-- Forum End -->




	
	</div>
	
	
	
	<table width="100%">
	<tbody><tr valign="top">
		<td class="TinyText" align="left">
		    <a id="ctl00_PermaLink" href="http://www.codeproject.com/script/Articles/Article.aspx?aid=13390">PermaLink</a> | 
			<a id="ctl00_PrivacyLink" href="http://www.codeproject.com/info/privacy.aspx">Privacy</a> |
			<a id="ctl00_TermsOfUseLink" href="http://www.codeproject.com/info/TermsOfUse.aspx">Terms of Use</a>
			<br>Last Updated: 11 Jun 2008<br>
			Editor: <a id="ctl00_ArticleEditor" href="http://www.codeproject.com/script/Membership/View.aspx?mid=3873871">Sean Ewington</a><br>
		</td>
		<td class="TinyText" align="right" valign="top">
			Copyright 2006 by Billy McCafferty<br>Everything else
			Copyright © <a href="mailto:webmaster@codeproject.com">CodeProject</a>, 1999-2010 <br>
			Web17 |
			<a id="ctl00_AdvertiseLink" href="http://www.codeproject.com/info/MediaKit.aspx">Advertise on the Code Project </a>
		</td>
	</tr>
	
	</tbody></table>
	
	<center>
		
	</center>

</div>
</div>	
	
<div>


</div>

<br>







</body>
</html>
